import()
when importing non-ESM (i. e. CommonJS modules). 3 min read
·
Feb 14, 2018Actually there are a lot of cases to consider when using import()
.
But let’s start with few naming hints:
Source: the module containing the import()
expression
Target: the module referenced by the request in the import()
expression
non-ESM: a CommonJs or AMD module not setting __esModule: true
transpiled-ESM: a CommonJS module setting __esModule: true
because it was transpiled from ESM
ESM: a normal EcmaScript module
strict-ESM: a more strict EcmaScript module i. e. from a .mjs
file
JSON: a json file
These cases need to be considered:
__esModule
)Here are some examples to make it easier to understand:
// (A) source.js
import("./target").then(result => console.log(result));// (B) source.mjs
import("./target").then(result => console.log(result));// (1) target.js
exports.name = "name";
exports.default = "default";// (2) target.js
exports.__esModule = true;
exports.name = "name";
exports.default = "default";// (3) target.js or target.mjs
export const name = "name";
export default "default";// (4) target.json
{ name: "name", default: "default" }
Let’s start with the easy ones:
A3 and B3: import(ESM)These cases are actually covered by the ESM spec. They are the only ones spec’ed.
import()
will resolve to the namespace object of the target module. For compatibility we also add a __esModule
flag to the namespace object to be usable by transpiled imports.
{ __esModule: true, name: "name", default: "default" }A1: import(CJS)
We import a CommonJs module. webpack 3 just resolved to the value of module.exports
. webpack 4 will now create a artificial namespace object for the CommonJs module, to let import()
consistently resolve to namespace objects.
The default export of a CommonJs module is always the value of module.exports
. webpack also allows to pick properties from a CommonJs module via import import { property } from "cjs"
, so we allow this for import()
.
Note: In this case the property default
is hidden by the default default
.
// webpack 3B1: import(CJS).mjs
{ name: "name", default: "default" }// webpack 4
{ name: "name", default: { name: "name", default: "default" } }
In strict-ESM we don’t allow picking properties via import
and only allow the default export for non-ESM.
{ default: { name: "name", default: "default" } }A2: import(transpiled-ESM)
webpack supports the __esModule
flag, with upgrades a CJS module to a ESM.
{ __esModule: true, name: "name", default: "default" }B2: import(transpiled-ESM).mjs
In strict-ESM the __esModule
flag is not supported.
You could call this broken, but at least it’s consistent with node.js.
{ default: { __esModule: true, name: "name", default: "default" } }A4 and B4: import(json)
Property picking is also supported when importing JSON, even in strict-ESM.
JSON also exposes the complete object as default export.
{ name: "name", default: { name: "name", default: "default" } }
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4