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
importkeyword. 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
.mjsor.jsto 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-loaderfor 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-frontendis installed (it could be local to the package, or hoisted to a highernode_modulesdirectory) so we run:This is where Node.js throws
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]