Babel plugin that transforms ES2015 modules to SystemJS format
npx @tessl/cli install tessl/npm-babel-plugin-transform-es2015-modules-systemjs@6.24.0Babel plugin that transforms ES2015 module syntax to SystemJS format. This plugin converts standard ES2015 import/export declarations into System.register() calls compatible with the SystemJS universal module loader.
npm install --save-dev babel-plugin-transform-es2015-modules-systemjsbabel-template, babel-helper-hoist-variables, babel-runtimeThe plugin is used through Babel's plugin system rather than direct imports:
.babelrc
{
"plugins": ["transform-es2015-modules-systemjs"]
}Node API
const babel = require("babel-core");
const result = babel.transform(code, {
plugins: ["transform-es2015-modules-systemjs"]
});export default 42;
export const greeting = "Hello";
import { utils } from "./utils";System.register(["./utils"], function (_export, _context) {
"use strict";
var utils;
return {
setters: [function (_utils) {
utils = _utils.utils;
}],
execute: function () {
_export("default", 42);
const greeting = "Hello";
_export("greeting", greeting);
}
};
});The plugin exports a default function that follows Babel's plugin API structure.
/**
* Default export: Babel plugin factory function
* @param {Object} babel - Babel object containing types and other utilities
* @param {Object} babel.types - Babel types utility object for AST manipulation
* @returns {Object} Babel plugin object with visitor methods
*/
export default function ({ types }) {
return {
visitor: {
CallExpression(path, state) { /* Handle dynamic imports */ },
ReferencedIdentifier(path, state) { /* Handle __moduleName */ },
Program: {
enter(path, state) { /* Initialize plugin state */ },
exit(path, state) { /* Transform module structure */ }
}
}
};
}The plugin accepts configuration options through Babel's plugin options system via state.opts.
interface PluginState {
opts: {
/** Name of the global SystemJS object (default: "System") */
systemGlobal?: string;
};
contextIdent: Identifier;
}
interface NodePath {
node: Node;
scope: Scope;
get(key: string): NodePath;
replaceWith(node: Node): void;
remove(): void;
isAssignmentExpression(): boolean;
isUpdateExpression(): boolean;
isIdentifier(): boolean;
}
interface Identifier {
type: "Identifier";
name: string;
}Configuration Examples:
Via .babelrc with options:
{
"plugins": [
["transform-es2015-modules-systemjs", {
"systemGlobal": "SystemJS"
}]
]
}Via Node API:
babel.transform(code, {
plugins: [
["transform-es2015-modules-systemjs", {
systemGlobal: "SystemJS"
}]
]
});The plugin handles the following ES2015 module patterns:
import foo from "module" → SystemJS setter with default property accessimport { bar } from "module" → SystemJS setter with named property accessimport * as ns from "module" → SystemJS setter with full module assignmentimport "module" → SystemJS dependency without setter bodyexport default value → _export("default", value)export const foo = 1 → Variable declaration + _export("foo", foo)export { bar } from "module" → SystemJS setter with re-export logicexport * from "module" → SystemJS setter with property enumerationimport("module") → _context.import("module")__moduleName → _context.idThe plugin implements several Babel visitor methods to transform different types of AST nodes.
interface PluginVisitor {
/** Transforms dynamic import() calls to SystemJS context.import() */
CallExpression(path: NodePath, state: PluginState): void;
/** Transforms __moduleName references to context.id */
ReferencedIdentifier(path: NodePath, state: PluginState): void;
/** Plugin lifecycle methods for program-level transformations */
Program: {
/** Initialize plugin state and generate unique identifiers */
enter(path: NodePath, state: PluginState): void;
/** Main transformation logic converting ES2015 modules to SystemJS */
exit(path: NodePath, state: PluginState): void;
};
}{
"plugins": ["transform-es2015-modules-systemjs"]
}babel --plugins transform-es2015-modules-systemjs script.jsconst babel = require("babel-core");
const result = babel.transform(sourceCode, {
plugins: ["transform-es2015-modules-systemjs"]
});
console.log(result.code); // SystemJS formatted outputbabel.transform(code, {
plugins: [
["transform-es2015-modules-systemjs", {
systemGlobal: "SystemJS" // Uses SystemJS.register instead of System.register
}]
]
});The plugin works with Babel's built-in module configuration options:
babel.transform(code, {
moduleIds: true, // Enable module ID generation
moduleId: "my-custom-module-name", // Specify custom module name
plugins: ["transform-es2015-modules-systemjs"]
});This produces:
System.register("my-custom-module-name", [], function (_export, _context) {
// module body
});The plugin generates SystemJS modules using the System.register() format:
/**
* SystemJS module registration format produced by the plugin
* @param {string[]} dependencies - Array of module dependency paths
* @param {Function} factory - Factory function that defines the module
*/
System.register(dependencies, function(_export, _context) {
"use strict";
return {
setters: [
// Functions for receiving dependency exports
],
execute: function() {
// Module initialization and export code
}
};
});The generated modules are compatible with SystemJS loaders and can be used in browsers and Node.js environments that support SystemJS.
The plugin relies on several Babel helper packages for its functionality:
/** Core dependencies used internally by the plugin */
interface PluginDependencies {
/** Template builder for generating SystemJS register calls */
"babel-template": {
/** Creates template functions from string templates */
default(template: string): (...args: any[]) => Node;
};
/** Variable hoisting utilities for proper scoping */
"babel-helper-hoist-variables": {
/** Hoists variables to the top of their containing scope */
default(path: NodePath, emit: (id: Identifier) => void): void;
};
/** Runtime helpers for generated code */
"babel-runtime": {
/** Polyfills and helper functions */
};
}