Skip to content
This repository has been archived by the owner on Apr 16, 2020. It is now read-only.

Document behavior of ESM packages that lack main field #73

Closed
coreyfarrell opened this issue Jul 4, 2019 · 8 comments
Closed

Document behavior of ESM packages that lack main field #73

coreyfarrell opened this issue Jul 4, 2019 · 8 comments

Comments

@coreyfarrell
Copy link
Member

Example package.json:

{
  "name": "foo-bar",
  "type": "module"
}

Assuming index.js exists, what is the expected behavior of import something from 'foo-bar'? Is this expected to throw a resolve error due to "type": "module" as would happen trying to import from a directory? If "type": "module" where not specified (foo-bar is CJS) would the import statement follow the CJS resolution rules and find index.js?

I thought of this looking at #72, thinking about expected behavior when specifying "exports": {} without main. It seems like this could be uses to provide CLI only packages that intentionally do not provide an API.

@ljharb
Copy link
Member

ljharb commented Jul 4, 2019

In CJS, omitting a main and an index.js makes your package not requirable. I’d expect the same for ESM.

@coreyfarrell
Copy link
Member Author

My question is about omitting main but providing an index.js. I'd expect this to fail to resolve when the package type is module?

@jkrems
Copy link
Contributor

jkrems commented Jul 4, 2019

I would assume that ESM defaults to main being ./index (or ./index.js). The side effect of ./index would be that only CJS files would work (or an extensionless file in the case above... maybe?).

@jkrems
Copy link
Contributor

jkrems commented Jul 4, 2019

It seems like this could be uses to provide CLI only packages that intentionally do not provide an API.

I'd love to define main in terms of exports. In which case setting main to an empty array or null would be perfectly valid once that syntax is supported in exports. And it would cleanly prevent an import of the package with a more meaningful error than "module not found".

@ljharb
Copy link
Member

ljharb commented Jul 4, 2019

I would expect it to work, with an index.mjs as well.

@jkrems
Copy link
Contributor

jkrems commented Jul 4, 2019

With extension resolution magic turned on - yes. Without - I wouldn't expect index.mjs to work in the case above.

@ljharb
Copy link
Member

ljharb commented Jul 4, 2019

In ESM even without extension resolution, I’d expect a literal index.mjs to work.

@coreyfarrell
Copy link
Member Author

I would assume that ESM defaults to main being ./index (or ./index.js). The side effect of ./index would be that only CJS files would work (or an extensionless file in the case above... maybe?).

See https://nodejs.org/dist/latest/docs/api/modules.html#modules_all_together, specifically LOAD_AS_DIRECTORY. If "main" is a falsy value, GOTO 2. which is does LOAD_INDEX(x). So if main is falsy I'd expect ESM to fail here unless the target is a CJS module. An edge case is what happens if main is falsy and type: module is set but index.cjs, index.json or index.node exist.

IMO https://nodejs.org/dist/latest/docs/api/esm.html#esm_package_entry_points should be explicit about what happens when main is not specified. The edge cases I can think of:

  1. type !== 'module' - use CJS resolution algorithm
  2. type === 'module' and index.cjs, index.json or index.node exist - use CJS resolution algorithm but excluding extension .js?

Also noticed while looking at this https://nodejs.org/dist/latest/docs/api/modules.html#modules_all_together LOAD_INDEX and LOAD_AS_FILE list .js, .json and .node extensions. Should .cjs be listed here, and if so what priority does it have? Or is .cjs only resolved when --experimental-modules is enabled?

Another related edge case is what happens when an in-package directory contains an index.cjs. Should import './some-directory'; find ./some-directory/index.cjs?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants