node icon indicating copy to clipboard operation
node copied to clipboard

feature: allow usage of both `"exports"` and non-`"exports"` resolution

Open llllvvuu opened this issue 1 year ago • 3 comments

What is the problem this feature will solve?

(summary from https://github.com/vercel/next.js/pull/50357#issuecomment-1920297413)

In a project that exports many vendored packages, it is not feasible to copy every "main" from each vendored package to the "exports" map. But it is desirable to map some exports, such as: 'next/link' -> ./link.js

We are not able to do this, due to:

preventing any other entry points besides those defined in "exports"

Existing packages introducing the "exports" field will prevent consumers of the package from using any entry points that are not defined, including the package.json (e.g. require('your-package/package.json')). This will likely be a breaking change.

The following advice is not feasible in the situation mentioned above:

To make the introduction of "exports" non-breaking, ensure that every previously supported entry point is exported. It is best to explicitly specify entry points so that the package's public API is well-defined.

What is the feature you are proposing to solve the problem?

~~* Allow putting something like:~~

"./*": "./*.js",
"./dist/*": null,

~~to remove a pattern from the "exports" map~~

A few ideas:

  • Have "exports" support folders as modules, i.e. to check for package.json and index.js. Then I can just do
"./dist/*": "./dist/*",

and dist/compiled/regenerator-runtime will be importable even if it is a directory with a package.json pointing to runtime.js

  • Or, add a config like "resolveIfNotInExports" so that e.g. dist/compiled/regenerator-runtime still resolves if I set it to null

  • Or, if we want to maintain privacy, reserve some value besides null to tell Node.js to use the default algorithm:

"./dist/*": "default",

This way we don't make anything outside dist/ public.

What alternatives have you considered?

Users just have to import Link from "next/link.js"

llllvvuu avatar Feb 01 '24 01:02 llllvvuu

Allow putting something like: to remove a pattern from the "exports" map

This already works exactly as stated.

Jamesernator avatar Feb 02 '24 09:02 Jamesernator

For reference, the exact section of the docs that mentions it is https://github.com/nodejs/node/blob/37ba7a36e9101861bf002f55e0cf36eb050d1b84/doc/api/packages.md#L557-L575

Regarding your second point:

  • Add a config like "resolveIfNotInExports" so that e.g. dist/compiled/regenerator-runtime still resolves

Can you clarify what that would look like?

aduh95 avatar Feb 02 '24 10:02 aduh95

Allow putting something like: to remove a pattern from the "exports" map

This already works exactly as stated.

Goot catch, thanks. I've striked that part out.

Regarding your second point:

  • Add a config like "resolveIfNotInExports" so that e.g. dist/compiled/regenerator-runtime still resolves

Can you clarify what that would look like?

Instead of making foo/bar inaccessible like:

"./foo/*": "./foo/*",
"./foo/bar/*": null,

, what I want is to be able to make foo/bar/* use default module resolution. So the "resolveIfNotInExports" idea was to be able to reconfigure null to mean this. But to be honest, it's a weird idea and it would also expose unrelated paths like "baz". I think what I really want is just for "exports" to support folders as modules, i.e. to check for package.json and index.js.

llllvvuu avatar Feb 02 '24 17:02 llllvvuu

There has been no activity on this feature request for 5 months. To help maintain relevant open issues, please add the https://github.com/nodejs/node/labels/never-stale label or close this issue if it should be closed. If not, the issue will be automatically closed 6 months after the last non-automated comment. For more information on how the project manages feature requests, please consult the feature request management document.

github-actions[bot] avatar Aug 01 '24 01:08 github-actions[bot]