How to load named exports with SystemJS
Asked Answered
T

1

4

If I have a lib, say utils.js which looks like this

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

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

Which can be used as follows

import {foo} from './libs/utils';

console.log(foo());

Not very spectacular, but I get the feeling that this problem is the origin of the issue described in this post. Anyway I cannot get this to work in combination with SystemJS. I have to change the code to fix it

import utils from './libs/utils';

console.log(utils.foo());

Here is my systemjs-config file:

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'
});

So, it seems only the exports object can be loaded and not the named export. Can this somehow be fixed?

UPDATE I get the impression it could be fixed with formats

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

But so far it gives the same problems

Trombidiasis answered 23/2, 2017 at 10:24 Comment(0)
B
4

This behavior is not SystemJS specific. SystemJS behaves like this since version 0.20 because this is what ES6 module interoperability is being standardized to.

When, as in your question, you are importing CommonJS modules (exported via module.exports) using ES6 import, you will only get the entire export, and you cannot immediately destructure the exported names.

However, when you are importing modules which are exported via ES6 export, you will be able to destructure the exported names.

So, it's all by design. Guy Bedford wrote about this on his blog and referenced the module standardization that is going on for NodeJS:

... named exports will no longer be permitted when importing a CommonJS module from an ES module, and is discussed at https://github.com/nodejs/CTC/pull/60/files#diff-2b572743d67d8a47685ae4bcb9bec651R217.

That is, import { name } from 'cjs.js', where cjs.js is a CommonJS module will no longer be supported, and instead will require import cjs from 'cjs.js'; cjs.name.

An interop workaround by using __esModule:

We will continue to support the __esModule flag in interop though, allowing lifting of named exports for these cases.

So if the cjs.js module was written:

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

then it would be possible to have import { name } from 'cjs.js';, even though cjs.js is a CommonJS module, although this __esModule will eventually in the longer term be deprecated as well.

Benton answered 4/11, 2017 at 6:59 Comment(1)
It's not destructuring, even if the shorthand syntax is loosely the same.Docilla

© 2022 - 2024 — McMap. All rights reserved.