nodejs / modules

Node.js Modules Team

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Feature: Specifier resolution customization

GeoffreyBooth opened this issue · comments

ESM supports intra-package absolute specifiers (/top-level-dir/module.js) relative to a package root to avoid long unreadable ../../../top-level-dir/module.js chains. This is currently possible in CommonJS.

ESM supports alternative resolution when running tests in order to achieve convention-driven mocking: import './x' prefers ./x.test.js if it exists, rather than the usual ./x.js. This is currently possible in CommonJS.

@-prefixed bare-specifiers that refer to dependencies via an out-of-band manifest file (that defines the mapping similar to package-name-maps) can be loaded by Node without a build step.

If I forget to list all my dependencies in package.json, I could run my Node app in a strict asserting mode where name resolution will fail if my code accidentally imports:

  • bare-specifiers not explicitly listed as dependencies (this can be achieved today for the top level project by installing dependencies with the npm option --global-style at the cost of having one layer of nesting of installed modules)
  • relative-specifiers that wander into dependencies, i.e. node_modules

I can write a small sample module on a web-based JavaScript editor like JS Bin that can import modules from NPM (e.g. the unpkg use case).

I can deploy an app into production, but serve common modules like RxJs from a CDN.

I can depend on a dev build during development and a prod build in production.

Use case 23, 24, 26, 27, 29, 30, 31, 33. See also #109 for compatibility with browsers.

ESM supports intra-package absolute specifiers (/top-level-dir/module.js) relative to a package root to avoid long unreadable ../../../top-level-dir/module.js chains

It does as ESM? How?

It does as ESM?

The feature request is that it does somehow.

Right, but how does CJS support that?

commented

by hacking Module._resolveFilename, which i would not consider a model to follow. right now node's esm has resolve hooks which can handle this use case.

See module-alias as an example.

@GeoffreyBooth To clarify would this mean that / no longer refers to the root of the fs when using import?

To clarify would this mean that / no longer refers to the root of the fs when using import?

@bmeck It would mean that it could be customizable. For example, Meteor does this today. From https://guide.meteor.com/structure.html#intro-to-import-export:

import '../../api/lists/methods.js';  // import from relative path
import '/imports/startup/client';     // import module with index.js from absolute path

The /imports/startup in the second line is relative to the root of the app, not to the root of the file system.

Meteor is transpiling these lines, so it’s easy for it to remap the absolute path. I think the feature request would be that such shenanigans remain possible in Node in ESM without requiring transpilation. Obviously it wouldn’t be the default (how would Node know what the “root” should be?) but it should be possible through a loader or some other opt-in method.

I think that (short of the hack mentioned earlier) since this isn't actually a feature of CJS without transpilation, we should descope it as being a feature of ESM.

I’m not sure that Meteor accomplishes this via transpilation, I just know that it is transpiling. It might very well be using one of those hacks. I think it’s a reasonable request that ESM be similarly hackable.