govuk-frontend: ES Modules can't be imported without a bundler
Hello! š
Loved seeing the ES Modules support land yesterday š
Description of the issue
Iām unfortunately seeing an Error [ERR_PACKAGE_PATH_NOT_EXPORTED]
thrown without a bundler
Steps to reproduce the issue
This happens with a plain native Node.js import
from another *.mjs
file
Current (see package.json)
Missing the main
or default export
"exports": {
"import": "./govuk-esm/all.mjs"
}
Fixed (see exports documentation)
Provided a main
or default export for both import
and require()
"exports": {
".": {
"import": "./govuk-esm/all.mjs",
"require": "./govuk/all.js"
}
}
Actual vs expected behaviour
Nodeās resolver node:internal/modules/esm/resolve
doesnāt have enough info to import 'govuk-frontend'
Unlike the Import JavaScript using a bundler guidance regarding webpack, I canāt teach Node.js to break the ESM rules.
With the fix above, I sadly hit another challenge. Node.js wouldnāt attempt to resolve .mjs
files as thereās no package.json "type": "module"
and extensions are mandatory for CommonJS and ESM compatibility š¬
Mandatory file extensions A file extension must be provided when using the
import
keyword. Directory indexes (e.g.'./startup/index.js'
) must also be fully specified.This behavior matches how import behaves in browser environments, assuming a typically configured server.
I wasnāt fully out of options though.
I tried the new ESM aware TypeScript compiler but it also had issues importing without extensions. Microsoft have added some good release notes on type
in package.json
and New Extensions plus challenges involved.
Hope these notes help, itās fab to see whatās coming š
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 18 (16 by maintainers)
@vanitabarrett Hereās a super minimal one: https://github.com/colinrotherham/govuk-frontend-esm-sample
Or via mocha
Ah interesting, thanks! Will take a look @colinrotherham
@colinrotherham Would you mind trying out this pre-release, when you get some time? It includes file extensions for all imported component JS files, so Iām hoping that may fix the issue š¤
npm install --save "alphagov/govuk-frontend#872b5c1f"
Note: the implementation of this may change - weāre currently weighing up shipping as
.mjs
or.js
to make things simpler. But either way, this should help us understand if specifying all file extensions will fix the issue.Not sure who started the package.json
"sass"
field really!I had a quick look and your
"sass"
field was added in June 2018 (by @nickcolley āļø) but itās likely one of the early Compass/Grunt/Gulp node-sass{ importer }
plugins that used"sass"
tooA bit later
sass-loader
for webpack added"sass"
support in December 2018Thereās also the original (~2015) Eyeglass importer from the Sass people:
Foundation https://github.com/foundation/foundation-sites/blob/develop/package.json#L142
Must have followed on from frameworks and pattern library tools adopting
style
? (Made popular by Browserify + Parcelify, PostCSS too)Package entry points
The docs arenāt brilliant and other tooling wonāt necessarily support the full spec https://nodejs.org/api/packages.html#package-entry-points
The webpack resolver appears to prefer
"exports"
so explains why excluding"sass"
caused https://github.com/alphagov/govuk-frontend/issues/2645Shorthand
Using the shorthand (following the documentation) would give us:
Regarding
"default"
being a more universal implementation (with polyfills etc perhaps):Longhand
But those
"./govuk/"
"./govuk-esm/"
package entry points were for compatibility to let tools know āthese paths are also availableā without trying to resolve from"main"
or"module"
insteadBut no, it doesnāt open up that directory/path
Youāll already be able to import a specific Sass stylesheet or nested polyfill directly
Typically youād use them for backwards compatibility when files move:
Found the code thatās causing us issues
We have a monorepo with a shared webpack.config.mjs. Some local packages need to know where
govuk-frontend
is installed (it could be local to the package, or hoisted to a highernode_modules
directory) so we run:This is where Node.js throws
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]