-
Notifications
You must be signed in to change notification settings - Fork 333
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ES Modules can't be imported without a bundler #2633
Comments
Could be the same issue affecting Rollup mentioned here #711 (comment) Looks like the fix is similarly needed for Similarly when using webpack to output a polyfill-light ESM bundle using (But this might be a side effect of our very ESM setup!) |
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 import { createRequire } from 'module'
// Avoids Node.js --experimental-import-meta-resolve
const require = createRequire(import.meta.url)
// Locate package
const pkgGovukFrontend = dirname(require.resolve('govuk-frontend')) This is where Node.js throws [webpack-cli] Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in /path/to/project/node_modules/govuk-frontend/package.json
at new NodeError (node:internal/errors:372:5)
at throwExportsNotFound (node:internal/modules/esm/resolve:472:9)
at packageExportsResolve (node:internal/modules/esm/resolve:693:7)
at resolveExports (node:internal/modules/cjs/loader:482:36)
at Function.Module._findPath (node:internal/modules/cjs/loader:522:31)
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:919:27)
at Function.resolve (node:internal/modules/cjs/helpers:108:19)
at file:///path/to/project/packages/frontend-assets/webpack.config.mjs:9:42
at ModuleJob.run (node:internal/modules/esm/module_job:198:25)
at async Promise.all (index 0) {
code: 'ERR_PACKAGE_PATH_NOT_EXPORTED'
} |
We're experiencing this too. No bundler being used, just using As it happens we're also supporting ESM/CommonJS consumers in our own module and although we've taken a slightly different approach (transpiling to CommonJS for all consumers) we have found success with the following config: {
"main": "dist/module.js",
"module": "dist/mjs/module.js",
"exports": {
"import": "./dist/mjs/esm-wrapper.js",
"require": "./dist/module.js"
},
...
} Where the Adding |
Thanks for raising this issue @colinrotherham and @lhokktyn , this is really detailed and helpful. We've been working on a fix for this issue which sounds similar #2643 and wondered if you'd be interested in helping test if this fix also solves the issues you're seeing? You can test this by installing our pre-release:
|
Thanks @vanitabarrett I've given it a go Brilliantly our webpack build can now locate SassI need to dig into this some more but our webpack I've seen that Perhaps without
Edit: This minor fix works for "exports": {
"import": "./govuk-esm/all.mjs",
"require": "./govuk/all.js",
"sass": "./govuk/all.scss"
}, JavaScriptImport JavaScript using a bundler {
test: /\.mjs$/,
type: 'javascript/auto',
resolve: {
fullySpecified: false
}
} We can't benefit from this workaround as we also add: exclude: /node_modules/, This is so our full list of loaders: source maps, TypeScript, Babel, Sass, PostCSS (autoprefixer, minifier) don't process and/or transform external code. We don't want to tamper with external code until optimisation time. That said, the fix for us would be to add this everywhere instead: // enable ESM cheat code for govuk-frontend
exclude: /node_modules\/(?!govuk-frontend)/, Without it we see this error for every module:
|
@vanitabarrett Here's a fix that works for Node.js (ESM via webpack resolve workaround) and @import "govuk-frontend/govuk/base";
@import "govuk-frontend/govuk/core/all";
@import "govuk-frontend/govuk/objects/all"; "exports": {
".": {
"sass": "./govuk/all.scss",
"import": "./govuk-esm/all.mjs",
"require": "./govuk/all.js"
},
"./govuk/": "./govuk/",
"./govuk-esm/": "./govuk-esm/"
}, Although using dart-sass imports via |
Thanks for looking into this @colinrotherham , the team really appreciates it! I've been doing a bit of testing to try and make sure I understand the solution myself. Am I right in saying For importing any other sass files, it looks like |
Not sure who started the package.json I had a quick look and your A bit later There's also the original (~2015) Eyeglass importer from the Sass people: Foundation "eyeglass": {
"name": "foundation",
"sassDir": "scss",
"needs": ">=0.8.0",
"exports": false
}, Must have followed on from frameworks and pattern library tools adopting Package entry pointsThe docs aren't brilliant and other tooling won't necessarily support the full spec The webpack resolver appears to prefer ShorthandUsing the shorthand (following the documentation) would give us: "exports": {
"import": "./govuk-esm/all.mjs",
"require": "./govuk/all.js",
"sass": "./govuk/all.scss",
"style": "./dist/govuk-frontend-4.1.0.min.css",
"browser": "./dist/govuk-frontend-4.1.0.min.js",
"default": "./dist/govuk-frontend-4.1.0.min.js"
} Regarding
LonghandBut those "exports": {
".": {
"import": "./govuk-esm/all.mjs",
"require": "./govuk/all.js",
"sass": "./govuk/all.scss",
"style": "./dist/govuk-frontend-4.1.0.min.css",
"browser": "./dist/govuk-frontend-4.1.0.min.js",
"default": "./dist/govuk-frontend-4.1.0.min.js"
},
"./govuk/": "./govuk/",
"./govuk-esm/": "./govuk-esm/"
} But 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: "exports": {
".": "./dist/index.js",
"./old-export": "./dist/legacy/new-export.js"
} |
Thanks @colinrotherham that's really cleared a few things up! If you, or anyone else interested, would like to test with these changes, I've got a pre-release you can install by running:
|
@vanitabarrett Perfect! Yep that does the job and the webpack guidance works now 👍 Beyond webpack can we leave this issue open until Mandatory file extensions are added? One example is mocha (without Babel) running an ESM test file that imports > mocha "./path/to/test.spec.mjs" But without a bundler to help it's getting stuck on the first line of import { nodeListForEach } from './common' Without the Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/path/to/project/node_modules/govuk-frontend/govuk-esm/common' imported from /path/to/project/node_modules/govuk-frontend/govuk-esm/all.mjs
at new NodeError (node:internal/errors:372:5)
at finalizeResolution (node:internal/modules/esm/resolve:437:11)
at moduleResolve (node:internal/modules/esm/resolve:1009:10)
at defaultResolve (node:internal/modules/esm/resolve:1218:11)
at ESMLoader.resolve (node:internal/modules/esm/loader:580:30)
at ESMLoader.getModuleJob (node:internal/modules/esm/loader:294:18)
at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:80:40)
at link (node:internal/modules/esm/module_job:78:36) Thanks again for the quick Glad it's helped others too |
@vanitabarrett that's fixed the issue for our use case too. Thanks for the quick response on this 👍 |
@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 🤞
Note: the implementation of this may change - we're currently weighing up shipping as |
@vanitabarrett Sorry, few more in there!
See the Can either change those imports to |
Ah interesting, thanks! Will take a look @colinrotherham |
@colinrotherham Have you got a basic setup you could share with me for testing this? When I tested it locally myself I didn't get that particular error 🤔 |
@vanitabarrett Here's a super minimal one: npm ci
npm start Or via mocha npm test |
Hi @colinrotherham , sorry for the slow response on this! I've been mulling over the best way for us to support this on GOV.UK Frontend (this PR if you're interested) . If you have the time to test another pre-release, you can installing it via:
|
Hi @vanitabarrett great work 🎉 Yep it's working perfectly now with mocha (via ESM) and webpack without |
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 bundlerSteps to reproduce the issue
This happens with a plain native Node.js
import
from another*.mjs
fileCurrent (see package.json)
Missing the
main
or default exportFixed (see exports documentation)
Provided a
main
or default export for bothimport
andrequire()
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 😬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
inpackage.json
and New Extensions plus challenges involved.Hope these notes help, it's fab to see what's coming 🚀
The text was updated successfully, but these errors were encountered: