Import named vs default from CommonJS packages #260
Description
In the discussion regarding dynamic modules and CommonJS named exports, and whether or not it’s worth shipping support for import
statements of CommonJS packages’ default exports if we can’t also support import
of named exports, I thought it might be useful to research just how common import
statements of named exports versus default exports are. I took my research repo consisting of the 941 packages on the public NPM registry that contain a "module"
field and I analyzed those packages’ import
statements.
Terminology
Import specifiers come in three types, per Babel’s AST:
- An
ImportSpecifier
is theshuffle
inimport { shuffle } from 'lodash'
. - An
ImportDefaultSpecifier
is the_
inimport _ from 'lodash'
. - An
ImportNamespaceSpecifier
is the* as _
inimport * as _ from 'lodash'
.
The import source is the 'lodash'
in the above examples. For the sake of simplicity, I’m only analyzing imports of package entry points (so not 'lodash/shuffle.js'
or './shuffle.js'
). The import source is considered ESM if its package.json
has a "module"
field, or CommonJS otherwise.
Results
Where the source (e.g. 'lodash'
) is an ESM package:
Specifier Type | Count | % |
---|---|---|
ImportSpecifier | 4,234 | 54% |
ImportDefaultSpecifier | 3,483 | 44% |
ImportNamespaceSpecifier | 171 | 2% |
Where the source (e.g. 'lodash'
) is a CommonJS package:
Specifier Type | Count | % |
---|---|---|
ImportSpecifier | 14,816 | 44% |
ImportDefaultSpecifier | 17,751 | 52% |
ImportNamespaceSpecifier | 1,480 | 4% |
With regards to the CommonJS named vs default export debate:
- 52% of all import specifiers (specifiers, not entire
import
statements) are importing a CommonJS package’s default export:import _ from 'lodash'
. - 44% are importing named exports from a CommonJS package:
import { shuffle } from 'lodash'
.
So if we were to allow ImportDefaultSpecifiers and ImportNamespaceSpecifiers but not ImportSpecifiers, which is the option currently being discussed, in this corpus at least we would cause 44% of all ImportSpecifiers to throw errors. An import
statement importing named exports often imports several at a time (e.g. import { shuffle, throttle } from 'lodash'
) so the percentage of import
statements using ImportSpecifiers is lower than 44% of all specifiers being ImportSpecifiers, but the percentage of such import
statements is surely still significant. A very large percentage of users will likely expect import
statements like import { shuffle } from 'lodash'
to work, as such statements are commonplace in user ESM code.