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

ESM module for both Node.js and the Browser? #1154

Closed
endel opened this issue Nov 26, 2020 · 10 comments
Closed

ESM module for both Node.js and the Browser? #1154

endel opened this issue Nov 26, 2020 · 10 comments

Comments

@endel
Copy link

endel commented Nov 26, 2020

Describe the bug

The httpie package specifies "browser" paths on its package.json multiple times, but frontend build tools don't seem to pick up the correct file (always selecting node/index.mjs)

screenshot

ERROR

[vite] Dep optimization failed with error:
Could not load http (imported by node_modules/httpie/node/index.mjs): ENOENT: no such file or directory, open 'http'
[Error: Could not load http (imported by node_modules/httpie/node/index.mjs): ENOENT: no such file or directory, open 'http'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: 'http',
  watchFiles: [
    '/Users/endel/projects/vite-esm-browser-node/node_modules/httpie/node/index.mjs',
    '/Users/endel/projects/vite-esm-browser-node/node_modules/vue/dist/vue.runtime.esm-bundler.js',
    '/Users/endel/projects/vite-esm-browser-node/node_modules/@vue/runtime-dom/dist/runtime-dom.esm-bundler.js',
    '/Users/endel/projects/vite-esm-browser-node/node_modules/@vue/shared/dist/shared.esm-bundler.js',
    '/Users/endel/projects/vite-esm-browser-node/node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js',
    '/Users/endel/projects/vite-esm-browser-node/node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js',
    'http',
    'https',
    'url'
  ]
}

Reproduction

I've created a repository describing this problem https://github.com/endel/esm-browser-node


In fact, this problem is present on every ESM JavaScript bundler, I've found it very difficult to search about this on the web and I appreciate if you could point me in the right direction in case there is some discussion already going on about this! 🙏

@aleclarson
Copy link
Member

aleclarson commented Nov 26, 2020

module is preferred over browser here:

export const mainFields = ['module', 'jsnext', 'jsnext:main', 'browser', 'main']

PR welcome that checks if browser field has .mjs extension before the line below:

for (const field of mainFields) {

@aleclarson
Copy link
Member

Reverted in 6ce6d5c

@aleclarson aleclarson reopened this Jan 2, 2021
@yyx990803
Copy link
Member

It still works for httpie because the browser field in exports is still prioritized. Technically, module is not a Node.js concept and should be treated as browser only.

@schickling
Copy link
Contributor

Can I override/modify this behavior somehow for my own project (or maybe even on a per dependency level)? (esbuild provides a similar option via --main-fields see here.)

@yyx990803
Copy link
Member

@schickling latest has again adjusted to prioritize browser. As a last resort you can always use alias for manual resolving.

@schickling
Copy link
Contributor

In my case I want to explicitly pick the module value as the browser value of the package in question (https://github.com/bvaughn/react-error-boundary/blob/master/package.json#L7) is set to a UMD build.

Could you provide an example of how to do this via alias?

@yyx990803
Copy link
Member

Please read the docs https://vitejs.dev/config/#alias

@schickling
Copy link
Contributor

I see. So if I'm understanding correctly there isn't a way via alias to override the "main field" behavior (e.g. pick module) but rather "hard code" the file path (equivalent to the value that's defined by module in the dependency's package.json). Not ideal but okay as a workaround.

@yyx990803
Copy link
Member

yyx990803 commented Jan 5, 2021

@schickling globally adjust main field resolving is actually less ideal, because you can accidentally break other packages that have different package.json export formats. Vite used to prioritize module over browser, while that makes some packages work better, it breaks another bunch of packages because some packages use the module field to point to Node.js ESM formats. So the safer route is actually to alias case by case.

@schickling
Copy link
Contributor

Yup, that's exactly what I was planning to do. I was just wondering whether there's a way to do the remapping indirectly on the "main field" level as opposed to directly on the file level via alias.

@github-actions github-actions bot locked and limited conversation to collaborators Jul 16, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants