Skip to content

Allow transpiling module formats other than ESM #1276

@matthewp

Description

@matthewp

tldr; Currently only ES Modules (modules containing the import or export keyword) are transpiled through Babel. Users of other formats, like CommonJS, would like to also be able to transpile their code for production.

This was discussed on a recent live stream (41:01) and at a contributors meeting (1:01:50)

The Problem

Users in legacy codebases using AMD or CommonJS might want to take advantage of some of the new JavaScript features like arrow functions and destructuring.

Currently in Steal this would require rewriting the module to use ESM syntax. For small modules this is simple, but in more complex cases it is not:

var Todo = require("./todo").Todo;

becomes:

import TodoModule from "./todo";

const { Todo } = TodoModule;

With very large files this can become burdensome.

Additionally, ESM forces strict mode, and some legacy code might be relying on sloppy mode features like arguments.callee.

The Solution

Allowing non-ESM module formats to also be transpiled can be provided via configuration. We will restrict this to package.json configuration, which almost all Steal users use now, for simplicity of implementation.

API

The API will be a new transpile configuration option. There will be one signature:

"transpile": true

This will transpile all code within that particular package. Note that if you are using Babel you still might want to configure the babelOptions to set which plugins and presets you want to use, otherwise it will use the defaults.

A typical use case might be like:

{
  "name": "my-app",
  "version": "1.0.0",
  "main": "index.js",

  "steal": {
    "transpile": true
  }
}

Which, within my-app/todo.js this:

class Todo {

}

module.exports = Todo;

Should transpile into:

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var Todo = function Todo() {
  _classCallCheck(this, Todo);
};

module.exports = Todo;

Implementation

To implement this, I would start by making each package's package.json object (represented internally as a pkgInfo I believe) available on the load.metadata object.

Then, in the instantiate hook, check for the presence of this transpile boolean, and call loader.transpile, just as currently happens with ES modules.

I believe this is a fairly easy change that could be done in a half sprint or so.

Tasks

  • - Create tests for CommonJS and AMD.
  • - Add the package.json to the load.metadata object in the locate hook.
  • - Checking load.metadata.package for the flag in the instantiate hook and call loader.transpile.

Note for future

Given that CommonJS and AMD are fading out of usage, it might not make sense to put too much effort to these formats. However, if this feature proves to be popular we could expand this option in the future to take a glob pattern so that you can only transpile some files within your project, if desired.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions