如何使用 Babel 在 ES6 中编写与 CommonJS、AMD 和浏览器兼容的模块?
How do you author a module that is compatible with CommonJS, AMD and Browser in ES6 with Babel?
在普通的 ES5 中,如果我想编写一个可以在服务器端(通过 CJS、AMD、RequireJS)或浏览器使用的包,我会这样做:
(function(name, definition)){
if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
module.exports = definition();
} else if (typeof define === 'function' && typeof define.amd === 'object') {
define(definition);
} else {
this[name] = definition();
}
}('foo', function foo(){
'use strict';
return 'foo';
})
在用 ES6 编写包时,我是如何实现这个功能的?
我尝试了什么:
if (typeof exports !== 'undefined' && typeof module !== 'undefined') export Foo;
else if (typeof define === 'function' && typeof define.amd === 'object') define(Foo);
else this['Foo'] = Foo;
在转译时,Babel 抛出一个错误:
SyntaxError: src/index.js: 'import' and 'export' may only appear at the top level (10:69)
9 |
> 10 | if (typeof exports !== 'undefined' && typeof module !== 'undefined') export Foo;
| ^
11 | else if (typeof define === 'function' && typeof define.amd === 'object') define(Foo);
12 | else this['Foo'] = Foo;
13 |
当我使用 module.exports
而不是 export
时确实有效,但是是否可以严格使用 ES6 来做到这一点?
所以没有真正的方法将 ES6 模块包含在通用模块定义中,因为 ES6 模块严格来说每个文件一个,所有导入和导出语句都必须位于顶层。
当加载器规范完成后,可能会有一种方法可以将模块添加到注册表中,这将是您将 ES6 模块包含在 UMD 中的方式,直到那时,因为没有浏览器真正支持 ES6 模块,您的唯一的目标是 AMD 和 CommonJS,但你应该使用许多编译器或 trnsspiler 之一,如 browserify 或 Babel 来为你做这件事。
您不会有一个通用输出,但 StealJS 可以将您的 Babel 转译 ES6 项目导出到 CommonJS、AMD 并作为一个独立项目。对于 CommonJS 和 AMD,您的原始模块结构将被保留,因此您仍然可以只加载您真正需要的依赖项。
project exporting 指南对其进行了更详细的解释,但在使用 NPM 工作流程时,这就是您的构建脚本的样子(如果包含,它还将构建 CSS/LESS/SASS 和其他依赖项):
{
dist: {
system: {
config: "package.json!npm"
},
outputs: {
"+cjs": {},
"+amd": {},
"+global-js": {},
"+global-css": {}
}
}
}
在普通的 ES5 中,如果我想编写一个可以在服务器端(通过 CJS、AMD、RequireJS)或浏览器使用的包,我会这样做:
(function(name, definition)){
if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
module.exports = definition();
} else if (typeof define === 'function' && typeof define.amd === 'object') {
define(definition);
} else {
this[name] = definition();
}
}('foo', function foo(){
'use strict';
return 'foo';
})
在用 ES6 编写包时,我是如何实现这个功能的?
我尝试了什么:
if (typeof exports !== 'undefined' && typeof module !== 'undefined') export Foo;
else if (typeof define === 'function' && typeof define.amd === 'object') define(Foo);
else this['Foo'] = Foo;
在转译时,Babel 抛出一个错误:
SyntaxError: src/index.js: 'import' and 'export' may only appear at the top level (10:69)
9 |
> 10 | if (typeof exports !== 'undefined' && typeof module !== 'undefined') export Foo;
| ^
11 | else if (typeof define === 'function' && typeof define.amd === 'object') define(Foo);
12 | else this['Foo'] = Foo;
13 |
当我使用 module.exports
而不是 export
时确实有效,但是是否可以严格使用 ES6 来做到这一点?
所以没有真正的方法将 ES6 模块包含在通用模块定义中,因为 ES6 模块严格来说每个文件一个,所有导入和导出语句都必须位于顶层。
当加载器规范完成后,可能会有一种方法可以将模块添加到注册表中,这将是您将 ES6 模块包含在 UMD 中的方式,直到那时,因为没有浏览器真正支持 ES6 模块,您的唯一的目标是 AMD 和 CommonJS,但你应该使用许多编译器或 trnsspiler 之一,如 browserify 或 Babel 来为你做这件事。
您不会有一个通用输出,但 StealJS 可以将您的 Babel 转译 ES6 项目导出到 CommonJS、AMD 并作为一个独立项目。对于 CommonJS 和 AMD,您的原始模块结构将被保留,因此您仍然可以只加载您真正需要的依赖项。
project exporting 指南对其进行了更详细的解释,但在使用 NPM 工作流程时,这就是您的构建脚本的样子(如果包含,它还将构建 CSS/LESS/SASS 和其他依赖项):
{
dist: {
system: {
config: "package.json!npm"
},
outputs: {
"+cjs": {},
"+amd": {},
"+global-js": {},
"+global-css": {}
}
}
}