Skip to content
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

Imply ES6 module package, when package.json contanis 'module':... #34027

Closed
dilyanpalauzov opened this issue Jun 23, 2020 · 9 comments
Closed
Labels
esm Issues and PRs related to the ECMAScript Modules implementation. feature request Issues that request new features to be added to Node.js.

Comments

@dilyanpalauzov
Copy link

In my package.json I have 'type':'module' and in my code I write import babel from '@rollup/plugin-babel. The package.json of the latter contains "main": "dist/index.js", "module": "dist/index.es.js" but there is no 'type':'module'. In turn nodejs concludes that @rollup/plugin-babel is commonjs and there is no way to use the default import from dist/index.es.js. This means I have to write babel.default in my code and I cannot use import {babel} from '@rollup/plugin-html.

• When NodeJS imports a package(.json) that contains 'main' and 'module' fields, but no 'type' field, from a package containing 'type':'module', implicitly conclude that the imported package is an ES6 module.

@dilyanpalauzov dilyanpalauzov changed the title Imply ES6 module package, when package.json contanis 'type': 'module' Imply ES6 module package, when package.json contanis 'module':... Jun 23, 2020
@dilyanpalauzov
Copy link
Author

This is for the cases lacking "exports" in package.json.

@himself65 himself65 added the esm Issues and PRs related to the ECMAScript Modules implementation. label Jun 29, 2020
@jsmith
Copy link

jsmith commented Jul 14, 2020

I've actually searched quite a bit about node and the package.json module field and haven't found much information. The only other resource I've found specifically about node and the module field is this unanswered StackOverlow question from ~ a year ago. Is there any plans to support this field? I'm coming at this from the perspective of a es module developer hoping to support nodejs and the browser. Thanks :)

@jgonggrijp
Copy link

Please don't adopt this proposal, as it would instantly break Underscore and probably many other packages as well. The module field was intended as a way for packages to publish their ESM entry point to environments that support it while still using main for the CommonJS entry point. If the presence of a module field would be interpreted as the whole package being ESM, that will break the main entry for everyone who is trying to use CommonJS.

If anything, the presence of both a main and a module field should be considered evidence that the package provides a mix of CommonJS and ESM modules, and that the author is probably not using .cjs extensions to single out the former.

@dilyanpalauzov
Copy link
Author

dilyanpalauzov commented Sep 4, 2020

How shall the presence of module: and the absence of 'type':'module' be interpreted?

@jgonggrijp
Copy link

No different from any other package with the absence of "type": "module", as far as I'm concerned: as "type": "commonjs". The module field is there for build tools like Rollup and Webpack, who will find it either way.

Better would be if Node.js could interpret the module field in the way it was intended: main is CommonJS and module is ESM.

In my ideal world, there wouldn't be such a rigid, restrictive segregation between ESM and CommonJS in the first place. For a package maintainer like myself, who is trying to cater to many environments and module systems at the same time, it is currently much easier to avoid the experimental ESM support in Node.js entirely and refer people to third-party tools like Rollup and esm instead. See jashkenas/underscore#2874 for some context.

@dilyanpalauzov
Copy link
Author

Take as example: https://github.com/rollup/plugins/blob/master/packages/babel/package.json . It has 'module' and 'main' fields, but not 'type' field. When I use the plugin over a rollup-configuration file, then rollup might load dist/index.es.js . When I write javascript file, that imports rollup and @rollup/plugin-babel, I have no way to use plugin-babel/dist/index.es.js (apart from probably spelling the full path in the import), when loading plugins for rollup.

This leads to a situation, where a package is read as ES6 module, when the package is a rollup plugin, loaded over a rollup configuration file, and the same package is used as commonjs, when rollup is initialized with direct javascript.

In fact, the main, module and type fields present four states:

  • the module is commonjs only and contains no ES6 module code
  • the module is ES6, but provides commonjs fallback
  • the module is ES6 without commonjs fallback
  • the module is commonjs, but also contains ES6 module code (current discussion)

Why is the last case necessary?

@jgonggrijp
Copy link

@dilyanpalauzov I'm failing to see the difference between case 2 and 4, other than which side of the equation you consider to be the "official" one. And that's exactly my gripe with the segregation in Node.js: why should one module system necessarily be "more important" than the other? Rollup takes a much friendlier approach in my opinion: every package that follows its main/module convention is simply both CommonJS and ESM, without any relative priority between them.

The problem you're describing boils down to Rollup and Node.js having different, incompatible conventions. To have them play nice together, at least one of them would have to adopt the convention of the other. Since we're discussing Node.js in here, that means it would have to adopt the notion that if you're doing an ESM package import and the target package has a module field, then you resolve from the module field instead of main.

Until the situation has improved, I simply suggest not mixing the systems. Rollup plugins are meant to run in Rollup context, which provides ESM support, so there is no need to involve the experimental ESM support from Node.js as well. If you want to use ESM code that was written for Rollup in a non-Rollup context, use a deep import path with the esm loader.

@bmeck
Copy link
Member

bmeck commented Sep 30, 2020

I'm not keen on supporting this proposal, use "type": "module" or ".mjs" files. Determining formats is already complex, and "module" isn't the only field in the wild that would hold this same kind of oddity. Additionally that only defines some hint about the nature of the entry point, not any subpaths such as import inside from "pkg/inside";. In addition supporting "module" has a conflict with "main" and "exports". I'd lean towards a won't fix on this issue due to these complexities.

CC: @nodejs/modules-active-members

@GeoffreyBooth
Copy link
Member

This was discussed in great depth when the current ES module support was designed. The short answer is that Node can’t support "module" because "module" already has a purpose: it defines an ESM entry point for bundlers such as Webpack. The many thousands of packages in the wild today already using "module" mostly aren’t publishing code usable as is by Node, and so Node’s inferring anything from "module" would most likely be erroneous.

This was discussed in the ES modules implementation announcement blog post: https://github.com/nodejs/modules/blob/master/doc/new-implementation-announcement.md#es-module-code-in-packages

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
esm Issues and PRs related to the ECMAScript Modules implementation. feature request Issues that request new features to be added to Node.js.
Projects
None yet
Development

No branches or pull requests

6 participants