从 ES6 模块生成 browserify 输出和 System.register() 模块?

Generating both browserify output & System.register() modules from ES6 modules?

我已经按照 2ality 的最终语法示例编写了 ES6 模块,没有 .js 后缀。

我还将模块组织成 vendor/project 目录层次结构和模块命名方案,因为 System.register() 模块格式有效地将已注册的模块放入同一命名空间。

问题如下,如果我引用2ality的例子:

//------ lib.js ------
export const sqrt = Math.sqrt;
export function square(x) {
    return x * x;
}
export function diag(x, y) {
    return sqrt(square(x) + square(y));
}

//------ main.js ------
import { square, diag } from 'lib';
console.log(square(11)); // 121
console.log(diag(4, 3)); // 5

以上直接在浏览器中运行良好,例如 traceur and es6-module-loader (see example-es6-modules.html)。当遇到 import 声明时,.js 后缀似乎会自动附加到文件名,并加载 lib.js。只要配置 System.paths 指向 vendor/project 目录的顶部,就可以直接在浏览器中执行 ES6 模块。

当使用 SystemJS builder (see example-system-register.html). As long as baseURL is set to the top of the vendor/project hierarchy (see builder.js 捆绑到单个 System.register() 模块格式文件时,以上内容也能正常工作。生成模块时,模块将以 vendor/project 前缀命名。

问题是当我尝试为 browserify, when carrying out the transform both traceur and es6ify 的输入生成 CommonJS 模块时,没有在 import 声明中为文件名附加 .js 后缀,导致错误以下几行:

$ cd src/es6
$ traceur --out ./out.js --modules commonjs gso/eonjs/EonJS.js

Error: File not found '/home/ ... /src/es6/gso/eonjs/MomentRecurRule'

以上错误是因为traceur没有在'gso/eonjs/MomentRecurRule'导入声明中添加.js后缀。否则会找到该文件。

如果 ES6 模块被转译为单独的 CommonJS 模块,browserify 会报告相同的错误,无法找到要导入的文件 - browserify 也不会类似地自动为导入文件名添加 .js 后缀。

接下来的问题是,ES6 模块在浏览器中执行没有问题,加载时也捆绑了 System.register() 模块,但如何转换为浏览器可执行文件?

相对路径的 browserify API 别名模块 ID:

var browserify = require('browserify');

var b = browserify();
b.add('./index.js');

b.require('./gso/eonjs/EonJS.js',  { expose: 'gso/eonjs/EonJS' });
b.require('./gso/eonjs/AbstractRecurRule.js', { expose: 'gso/eonjs/AbstractRecurRule' });
b.require('./gso/eonjs/MomentRecurRule.js', { expose: 'gso/eonjs/MomentRecurRule' });
b.require('./gso/eonjs/RRuleRecurRule.js', { expose: 'gso/eonjs/RRuleRecurRule' });
b.require('./gso/eonjs/RecurRuleContainer.js',  { expose: 'gso/eonjs/RecurRuleContainer' });
b.require('./gso/eonjs/Occurrence.js',  { expose: 'gso/eonjs/Occurrence' });

b.bundle().pipe(process.stdout);

快速浏览 CommonJS 以类似于 System.import() 的方式解析模块 ID 字符串(参见 RrequireJS Load JavaScript Files)。但是 browserify 需要这个额外的别名步骤。

grunt-browserify 任务:

    browserify: {
        options: {  // https://github.com/substack/node-browserify#browserifyfiles--opts
            require: [
                './src/commonjs/build/gso/eonjs/EonJS.js:gso/eonjs/EonJS',
                './src/commonjs/build/gso/eonjs/AbstractRecurRule.js:gso/eonjs/AbstractRecurRule',
                './src/commonjs/build/gso/eonjs/MomentRecurRule.js:gso/eonjs/MomentRecurRule',
                './src/commonjs/build/gso/eonjs/RRuleRecurRule.js:gso/eonjs/RRuleRecurRule',
                './src/commonjs/build/gso/eonjs/RecurRuleContainer.js:gso/eonjs/RecurRuleContainer',
                './src/commonjs/build/gso/eonjs/Occurrence.js:gso/eonjs/Occurrence'
            ]
        },
        debug: {
            debug: true,
            src: './index.js',
            dest: 'src/browserify/eonjs-traceur-debug.js'
        },
    },