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

Respect "exports" field in "package.json" #9509

Closed
mdreizin opened this issue Aug 1, 2019 · 27 comments · Fixed by #10953
Closed

Respect "exports" field in "package.json" #9509

mdreizin opened this issue Aug 1, 2019 · 27 comments · Fixed by #10953

Comments

@mdreizin
Copy link

mdreizin commented Aug 1, 2019

Feature request

What is the expected behavior?

It would be nice if webpack respects "exports" filed defined in package.json and follow a new resolution strategy.

What is motivation or use case for adding/changing the behavior?

This feature is just landed in node@12.7.0 (see proposal-pkg-exports).

How should this be implemented in your opinion?

  1. Read "exports" filed and create resolve.alias map internally (ie if resolve.useExports = true is turned on) using proposed resolution strategy.

  2. Allow to specify resolve.mainFields = ['exports'] and check for this reserved keyword. If it is found then apply proposed resolution strategy.

Are you willing to work on this yourself?

no

@sokra
Copy link
Member

sokra commented Aug 3, 2019

We can add this a experiment in webpack 5.

@mdreizin
Copy link
Author

mdreizin commented Aug 3, 2019

@sokra yes, it is good candidate to be included in webpack@5.

@webpack-bot
Copy link
Contributor

This issue had no activity for at least three months.

It's subject to automatic issue closing if there is no activity in the next 15 days.

@alexander-akait
Copy link
Member

Bump

@just-boris
Copy link

In addition to exports field, the new module system also allows imports to reference its own package name: nodejs/node#31002

More details on this feature: nodejs/modules#306

@mgol
Copy link

mgol commented Jan 22, 2020

The exports field is now available without any flag in Node.js v13.7.0 and it will be unflagged in the upcoming Node.js v12.15.0, scheduled for 2020-01-28.

@alexander-akait
Copy link
Member

@mgol Don't worry, we will implement that for webpack@5

@trusktr
Copy link

trusktr commented Feb 20, 2020

Is this in the beta yet? I would like to test it if so.

@alexander-akait
Copy link
Member

No, but in roadmap, it will be implemented to stable version

@trusktr
Copy link

trusktr commented Feb 20, 2020

Someone mind fixing the typo in the title, "filed" -> "field", so that this may appear more easily in search results?

@alexander-akait alexander-akait changed the title Respect "exports" filed in "package.json" Respect "exports" field in "package.json" Feb 21, 2020
@alexander-akait
Copy link
Member

Done

@mgol
Copy link

mgol commented Feb 28, 2020

An important note here: once the exports field is specified, it should be impossible to import any subpath that is not explicitly specified in the field.

More info at https://nodejs.org/api/esm.html#esm_package_exports:

In addition to defining an alias, subpaths not defined by "exports" will throw when an attempt is made to import them

import submodule from 'es-module-package/private-module.js';
// Throws ERR_MODULE_NOT_FOUND

This is a breaking change so please remember to include this restriction in Webpack 5.0.0 or it might have to wait until version 6!

@jhnns
Copy link
Member

jhnns commented Mar 15, 2020

We also need to decide: what happens with the module field?

Tbh I'm not really decided yet. I think we can ignore/deprecate it as long as we support the browser target. This would allow package authors to specify different implementations for Node and for the browser:

    "exports": {
        "node": "./node-impl.js",
        "browser": "./browser-impl.js"
    }

@trusktr
Copy link

trusktr commented Mar 16, 2020

@mgol Actually that isn't completely true (I had some confusion with that aspect of Node ESM). The Node.js docs need better documentation in this area (cc @MylesBorins).

As an example, the following

	"exports": {
		".": "./dist/index.js",
		"./": "./dist/"
	},

does allow you to import from any sub path of the dist folder.

EDIT: For more info see nodejs/node#14970.

Near the bottom of that issue I was confused, then Myles pointed out that exports supports re-directing the root path of a package (similar to that issue's OP's request for a mainDir option).

In particular, this comment describes the actual behavior that should be documented, as well as shows an example of modifying a package's "base path" or "root path".

What Myles said was only true in Node 13.1+. Prior to that, setting any value in the exports field, even a folder, caused all sub paths to be ignored by module resolution. Then Node 13.1 came out with ESM still behind a flag and the new behavior of not blocking sub path imports, and soon after that Node 13.2 removed the flag.

@vankop
Copy link
Member

vankop commented Apr 14, 2020

I will take a look on this

@jkrems
Copy link

jkrems commented Apr 15, 2020

If nodejs/node#32869 lands, this likely should include support for NODE_ENV based resolution ("production" and "development").

@siarheiyelin
Copy link

Are there any plans to support it in Webpack 4?

@alexander-akait
Copy link
Member

No, only webpack v5

@HomyeeKing
Copy link

I've met an issue that my npm package (foo for example) need to be used in both webpack4.x and webpack5.x

how to let webpack4.x recognize exports fileds?

Also I can't import through specific path(node_modules path) like foo/bar/baz.js in webpack5.x, got an error path ./bar/baz.js not exported from package

@alexander-akait
Copy link
Member

exports works only for webpack v5, v4 is not supported this

@ConnorLanglois
Copy link

I've run into an issue with this feature. Need to use @vespaiach/axios-fetch-adapter package, which imports modules from axios, but since axios has been updated to use the exports field this package now throws errors when trying to import those modules. I know we could wait for the package author to update their code, but as another option, could there be an option added to webpack to ignore this / force webpack to import the module? The exports still exist in axios in those files, so everything should work fine if webpack would just import it. It's along the lines of Yes, thank you webpack, the exports field is cool and has benefits, but right now I do not care, just import the package anyway please and anyone who uses this option would accept the fact they are playing with fire.

@ThiefMaster
Copy link

I fully agree with @ConnorLanglois. This MUST be something overridable. If I want to use an internal API, then this is my good right to do, and I understand the consequences (that it can break or be removed at any time). It's not up to webpack to decide that I can't.

FWIW, I'm trying to import axios/lib/helpers/isURLSameOrigin for some custom code that's directly related to axios so it even makes sense to use the same function there. If I have to copy this code into my project, there's actually a bigger risk of the two implementations diverging at some point, causing issues...

@snydergd
Copy link

snydergd commented Jan 29, 2024

In cases where you want to ignore the exports while package maintainers do updates, one option I am trying right now is to set the webpack config option resolve.exportsFields to an empty array. It seems to cause webpack to be OK with modules that aren't exported, though I'm not sure what other side effects larger projects might experience - and of course it's risky to use these long-term anyway, since then updates don't necessarily work.

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

Successfully merging a pull request may close this issue.