-
Notifications
You must be signed in to change notification settings - Fork 44
Proposal for transparent interop implementation #137
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
Many of us joined this group because we hope to see an ES modules implementation in Node that comes as close as possible to transparent interoperability, however people might define that. I think the group would benefit from sketching out just what such an implementation would look like, and hopefully coding it. If nothing else, it would provide a way to finally settle the disputes over what is or isn’t allowed per the spec, as there would be real code to point to; and chunks of the implementation could be recycled into loaders for the “pluggable loaders” implementation. A “transparent interop” implementation would also provide a nice contrast to “pluggable loaders”: what do we gain or lose from an explicitly non-transparent implementation where compatibility is opt-in, versus an implementation that tries to be as transparent as the spec allows? | ||
|
||
So here’s what I would take as a starting point: | ||
|
||
- I like that `experimental-modules` allows an ESM module to use an `import` statement to pull in a CommonJS module, even if it’s only as `import _ from 'underscore'` instead of `import { shuffle } from 'underscore'`. I want to keep at least that. | ||
|
||
- I’d like to see if someone can figure out a way to make `import { shuffle } from 'underscore'` work in a way that doesn’t break spec, or if not, we need to create a loader to support this (and a loader API to make such a loader possible). | ||
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong. |
||
|
||
- From the [NPM implementation](https://gist.github.com/ceejbot/b49f8789b2ab6b09548ccb72813a1054), I like that the Node runtime makes a guess at a script’s mode when running it via `node script.js`. I think this makes for a much better user experience, and is what users would prefer to happen. NPM’s implementation also adds a `--mode` flag to `node` so that people can explicitly run a script in ESM or CommonJS mode to skip the detection step; and this would also let Node to throw an exception if it’s not the module mode they’re expecting. The implementation also proposes extended Node’s shebang support to include `--mode`, which I also like. | ||
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong. |
||
|
||
- I want there to be a way to publish a package that can be imported as either ESM or CommonJS, without requiring a build step to create said package. I think this can be done if we adopt the `module` field into `package.json` (used by Webpack, among others) to define the ESM entry point, as a complement to the `main` field. The `module` field would go straight to the ESM root, e.g. `dist/index.js`, while `main` could go to a tiny CommonJS file that loads something like `esm` or `babel` first, e.g. `require('babel/register'); require('./dist/index.js');`. This `module` field would also provide the way for `import` statements to know when they can import a package as ESM. | ||
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong. |
||
|
||
- If people want to use `.mjs` to make it clear from the filename that their file is ESM, they can; but they wouldn’t need to. Command-line scripts like `babel` and `coffee` would continue to work, even as ESM. This also maintains parity with browsers, where people write [code](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) like `import * as myModule from '/modules/my-module.js';` | ||
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong. |
||
|
||
- I like the idea of using `import.meta.require` alongside `import` to handle both CommonJS and ESM _files_ within the same package boundary, so that a package can gradually transition from one to the other (probably with the help of transpilation to handle needing to know the module type of each file to be imported). So basically, within a package boundary, we _wouldn’t_ have transparent interop; but I haven’t really been expecting transparent interop to exist within a package, as then we might have trouble creating things like dual-mode packages (see above). `import.meta.require` would also be able to import CommonJS packages, but it wouldn’t be necessary since you could also use plain `import` (see above). Neither plain `require` nor `import.meta.require` would be able to import ESM. | ||
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong. |
||
|
||
- From the [zenparsing proposal](https://github.com/zenparsing/node-default-module-proposal), I like the idea of extending `import()` into CommonJS, to give such packages a way of importing ESM modules. Some packages will never convert, and they deserve a way to import packages that are published as ESM only. | ||
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong. |
||
|
||
This doesn’t cover every feature on our list, clearly, but hopefully covers some of the key points related to interoperability (transparent or otherwise). I welcome feedback. |
This comment was marked as off-topic.
Sorry, something went wrong.
This comment was marked as off-topic.
Sorry, something went wrong.