Meteor: Meteor 1.5 Dynamic Imports 'default' not as expected

Created on 24 Aug 2017  路  1Comment  路  Source: meteor/meteor

When a function is exported as default like

const NewsAlertComponent = ...
export default NewsAlertComponent;

When this is loaded by the new dynamic import

const module = await import(FILENAME);

or by

import(FILENAME).then((module)=> {
...
});

The default keyword does not mean NewsAlertComponent is loaded to module but instead, NewsAlertComponent is loaded inside module.default.


On the other hand, if the function is exported as an object like

const NewsAlertComponent = ...
export {NewsAlertComponent};

then it is possible to load NewsAlertComponent dynamically with

const {NewsAlertComponent} = await import(FILENAME);

or

import(FILENAME).then(({NewsAlertComponent})=> {
...
});

Most helpful comment

The subject of this issue and your expectation are not correct. Per the proposed ECMAScript specification, the dynamic import(...) call returns a Promise which eventually resolves to the module namespace of the specified import. As you've demonstrated above, this means that the "default" export from a module will be available as module.default. It might be worth pointing out here that in the case of a named, export default function declaration (i.e. export default function wheel() {}), the function is only named wheel in the local scope; the export-ed name will be default and thus it will not be called wheel on the module namespace, but rather just called default (module.default).

Going along with your expectation, there would be no way to access any of the (potential) named exports from FILENAME while also having a default export!

If you want the NewsAlertComponent to be available as module.NewsAlertComponent then you can export it from the module as a named export, but it will no longer be available as module.default:

export const NewsAlertComponent = ...

When retrieved via a dynamic-import(...) call, NewsAlertComponent would be available as:

import(FILENAME).then(module => console.log(module.NewsAlertComponent));

If you want NewsAlertComponent to be the default export but desire to call it by the name NewsAlertComponent and avoid the module symbol, you might explore using object destructuring:

import(FILENAME).then(({default: NewsAlertComponent}) => console.log(NewsAlertComponent));

You can read the specification I've mentioned above and browse the proposal repository for more information on the semantics which are supported but, in summary, the design of import(...) was not meant to have the same ergonomics as the import statement, and does not support clauses. While the specification I've linked to is a draft proposal, it is stage 3 and it is unlikely to change before it fully graduates.

For related reading, you might be interested in https://github.com/tc39/proposal-dynamic-import/issues/37, https://github.com/tc39/proposal-dynamic-import/issues/46, https://github.com/tc39/proposal-dynamic-import/issues/19 and http://2ality.com/2017/01/import-operator.html.

>All comments

The subject of this issue and your expectation are not correct. Per the proposed ECMAScript specification, the dynamic import(...) call returns a Promise which eventually resolves to the module namespace of the specified import. As you've demonstrated above, this means that the "default" export from a module will be available as module.default. It might be worth pointing out here that in the case of a named, export default function declaration (i.e. export default function wheel() {}), the function is only named wheel in the local scope; the export-ed name will be default and thus it will not be called wheel on the module namespace, but rather just called default (module.default).

Going along with your expectation, there would be no way to access any of the (potential) named exports from FILENAME while also having a default export!

If you want the NewsAlertComponent to be available as module.NewsAlertComponent then you can export it from the module as a named export, but it will no longer be available as module.default:

export const NewsAlertComponent = ...

When retrieved via a dynamic-import(...) call, NewsAlertComponent would be available as:

import(FILENAME).then(module => console.log(module.NewsAlertComponent));

If you want NewsAlertComponent to be the default export but desire to call it by the name NewsAlertComponent and avoid the module symbol, you might explore using object destructuring:

import(FILENAME).then(({default: NewsAlertComponent}) => console.log(NewsAlertComponent));

You can read the specification I've mentioned above and browse the proposal repository for more information on the semantics which are supported but, in summary, the design of import(...) was not meant to have the same ergonomics as the import statement, and does not support clauses. While the specification I've linked to is a draft proposal, it is stage 3 and it is unlikely to change before it fully graduates.

For related reading, you might be interested in https://github.com/tc39/proposal-dynamic-import/issues/37, https://github.com/tc39/proposal-dynamic-import/issues/46, https://github.com/tc39/proposal-dynamic-import/issues/19 and http://2ality.com/2017/01/import-operator.html.

Was this page helpful?
0 / 5 - 0 ratings