I am often writing packages and using the CJS-bridge technique to ensure that they are compatible with non-esm applications. However, for the applications that also use esm, it would be much nicer to be able to only use one version of esm instead of a lot. For example, I would often write a package like this:
{
"name": "my-package",
"main": "index.js",
"dependencies": {
"esm": "3.0.49"
}
}
And the index.js file would just be a CJS-bridge that requires and re-exports a .mjs file.
What I would like to be able to do is:
{
"name": "my-package",
"main": "index.js",
"module": "index.mjs",
"dependencies": {
"esm": "3.0.49"
}
}
And after I publish this package to npm, then install it into my application, I would import the package as follows:
import something from 'my-package';
Then, when I run my application using:
node -r esm my-application.js
I would like the import to completely skip the package's CJS bridge file and go straight to the .mjs file indicated in package.json's "module" field.
Hi @onlywei!
Support for module-alone has been requested before and rejected because it was non-standard but support with esm + module can totally be done. I'll look into it.
Update:
On rereading your request how are you using esm in your app? If you use node -r my-application.js where is esm being loaded?
@jdalton sorry, that was a typo. I am running my application like so:
node -r esm my-application.js
I've updated the original comment to reflect this as well.
Okay cool! I'm digging into this!
Update:
I'm going to have to follow this up and ensure .mjs is locked out of this behavior. I noticed you use .mjs and I'd suggest moving to .js if you want any of these compat/niceties as .mjs has none.
Update:
After thinking on this a bit while it would be neat to enable this the bridge file can export any part of the ES module it's bridging which means I can't assume the entire module is exported _(and so can't skip the bridge)_.
I can add an option to skip the bridge though, maybe skipBridges? What do you think?
@jdalton rather than skipBridges, perhaps it is more future proof to use something similar to Webpack's "resolve.mainFields" configuration?
Ah a mainFields option. I can dig that!
Update:
Patched https://github.com/standard-things/esm/commit/3ba3b473d1a35875a16ec4311e851975559d56f0.
@jdalton Great! Thank you so much! I shall be refreshing until release so I can test it :)
You can build it locally to test.
git clone https://github.com/standard-things/esm
cd esm
npm i
npm run build
cd ../myproject
Then point your node -r esm to node -r ../esm.
@jdalton doing that results in this error:
Error: Unknown [email protected] option: mainFields
Same here. Some traces
Error: Unknown [email protected] option: mainFields
at new <anonymous> (/home/charlike/tunnckoCore/get-installed-path/node_modules/esm/esm.js:1:45171)
at Function.module.exports.Mi.createOptions (/home/charlike/tunnckoCore/get-installed-path/node_modules/esm/esm.js:1:75361)
at new Mi (/home/charlike/tunnckoCore/get-installed-path/node_modules/esm/esm.js:1:72707)
at Vi (/home/charlike/tunnckoCore/get-installed-path/node_modules/esm/esm.js:1:74982)
at Fi (/home/charlike/tunnckoCore/get-installed-path/node_modules/esm/esm.js:1:73894)
at Function.get (/home/charlike/tunnckoCore/get-installed-path/node_modules/esm/esm.js:1:73631)
at Function.from (/home/charlike/tunnckoCore/get-installed-path/node_modules/esm/esm.js:1:73684)
at Hu (/home/charlike/tunnckoCore/get-installed-path/node_modules/esm/esm.js:1:216264)
at Object.<anonymous> (/home/charlike/tunnckoCore/get-installed-path/node_modules/esm/esm.js:1:224256)
at r (/home/charlike/tunnckoCore/get-installed-path/node_modules/esm/esm.js:1:569)
@onlywei @olstenlarck
Make sure you're referencing the local repo and not the installed npm dep. You should be able to delete the _node_modules/esm_ folder and it should still work when loading node -r ../esm.
@jdalton OK, I think I have a bit more information as to what is happening to me by adding console.log() statements in a bunch of places. Here was my debugging process:
["module"] in my application's package.json file.console.log() at the top of the esm.js file inside the copy of this repository that I cloned. This allowed me to confirm that my node -r ~/development/esm path is correct.Error: Unknown [email protected] option: mainFields when starting my application.node_modules directory that was using the cjs-bridge strategy, but did not properly configure the "module" field in package.json. At this point I knew that the cjs-bridge file of this package was calling require() onto its locally installed version of esm (3.0.51).package.json file inside the node_modules directory so that the "module" field points to the actual source file instead of the cjs-bridge file.console.log() statement to that package's cjs-bridge file.console.log() statement in that package's cjs-bridge file was still being executed right before the error!local repo
I'm not using cloned repository. I have installed esm in both the package that i'm working on and on the package that i'm using as dependency. Which in turn, have main pointing to the cjs bridge (src/index.js), and module pointing to the original source code file (src/index.mjs). I don't want to modify the defaults and don't want to add config to each of them - only option that i will use will be the mainFields.
You can see here example of how all my repos and packages looks like in the last weeks https://github.com/olstenlarck/hela/tree/v3-major/packages/cli.
@olstenlarck The support for mainFields is not in a published release yet.
Ooooh, i supposed that. Cool. That will fix my problems then.
Actually. Why no make the default for mainFields to be ["module", "main"]? I think that would be more stable and meaningful default. Many have module field which already points to ESM source.
I'm waiting to actually publish the 3.0.52 and i will try it immediately. You probably waiting the CI to finish, which for some reason takes too long for some versions, maybe restart those? ;d
Huh, the lovely AppVeyor - runs the tests twice: https://ci.appveyor.com/project/jdalton/esm/build/2120/job/oho0wumbbe3bfjok
Because from latest master with the bump to 3.0.52 commit it still fails with
/home/charlike/tunnckoCore/baw/node_modules/esm/esm.js:199
defineProperty(makeRequireFunction, shared.symbol.package, {
^
TypeError: Cannot read property 'package' of undefined
Without any esm options, just as is.
@olstenlarck I agree with you, but I think that would be a breaking change and require a 4.x release.
@jdalton I'm confused that this new feature is released as a semver patch release. Given the rules of semver, isn't it supposed to be 3.1.0?
v3.0.52 is released :tada:
_(Just to reiterate this feature will not work with .mjs files.)_