如何使用 SystemJS 加载命名导出

Posted

技术标签:

【中文标题】如何使用 SystemJS 加载命名导出【英文标题】:How to load named exports with SystemJS 【发布时间】:2017-07-13 18:28:49 【问题描述】:

如果我有一个库,请说utils.js,它看起来像这样

exports.foo = function () 
    return 'foo';
;

exports.bar = function () 
    return 'bar';
;

可以如下使用

import foo from './libs/utils';

console.log(foo());

不是很壮观,但我感觉这个问题是this 帖子中描述的问题的根源。无论如何,我无法将它与SystemJS 结合使用。我必须更改代码才能修复它

import utils from './libs/utils';

console.log(utils.foo());

这是我的 systemjs-config 文件:

SystemJS.config(
    map: 
        'plugin-babel': 'node_modules/systemjs-plugin-babel/plugin-babel.js',
        'systemjs-babel-build': 'node_modules/systemjs-plugin-babel/systemjs-babel-browser.js',
    ,
    packages: 
        '.': 
            defaultJSExtensions: 'js'
        
    ,
    transpiler: 'plugin-babel'
);

因此,似乎只能加载 exports 对象而不是命名导出。这可以以某种方式解决吗?

更新我觉得可以用formats修复它

    meta: 
    './libs/utils.js': 
        format: 'cjs'
    

但到目前为止它给出了同样的问题

【问题讨论】:

【参考方案1】:

这种行为不是 SystemJS 特有的。 SystemJS 从 0.20 版本开始就是这样,因为这是 ES6 模块互操作性的标准化。

当您使用 ES6 import 导入 CommonJS 模块(通过 module.exports 导出)时,您只会得到整个导出,并且不能立即解构导出的名称。

但是,当您使用通过 ES6 export 导出的 importing 模块时,您将能够解构导出的名称。

所以,这一切都是设计使然。 Guy Bedford 在他的博客上写了这篇文章,并引用了 NodeJS 正在进行的模块标准化:

... 导入时将不再允许命名导出 来自 ES 模块的 CommonJS 模块,在 https://github.com/nodejs/CTC/pull/60/files#diff-2b572743d67d8a47685ae4bcb9bec651R217.

import name from 'cjs.js',其中cjs.js是一个CommonJS 模块将不再受支持,而是需要 import cjs from 'cjs.js'; cjs.name.

使用__esModule 的互操作解决方法:

不过,我们将继续在互操作中支持 __esModule 标志, 允许针对这些情况取消指定的导出。

所以如果 cjs.js 模块被写入:

exports.__esModule = true;
exports.name = function ()   ... 

那么就有可能拥有import name from 'cjs.js';,甚至 虽然cjs.js 是一个CommonJS 模块,虽然这个__esModule 会 从长远来看,最终也会被弃用。

【讨论】:

它不是解构,即使简写语法大致相同。

以上是关于如何使用 SystemJS 加载命名导出的主要内容,如果未能解决你的问题,请参考以下文章

赛普拉斯与SystemJS

使用 SystemJS/jspm 在生产中加载异步、es5 模块

如何正确地将 Polyfills 添加到 SystemJS Angular 4 应用程序

我如何实际部署 Angular 2 + Typescript + systemjs 应用程序?

使用 SystemJS 即时转译 SASS

“systemjs-builder”:如何将 js 文件中的所有依赖项构建到一个 bundle.js 文件中