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

Vite doesn't support ESM packages with "exports" field in SSR #3953

Closed
6 tasks done
raythurnevoid opened this issue Jun 25, 2021 · 12 comments
Closed
6 tasks done

Vite doesn't support ESM packages with "exports" field in SSR #3953

raythurnevoid opened this issue Jun 25, 2021 · 12 comments
Labels
feat: ssr p2-edge-case Bug, but has workaround or limited in scope (priority)

Comments

@raythurnevoid
Copy link
Contributor

raythurnevoid commented Jun 25, 2021

Describe the bug

Because of this browserify/resolve#222 issue, Vite won't parse package.json "exports" field and will throw this error for packages that doesn't use "main" field:

3:03:07 AM [vite] Error when evaluating SSR module /src/components/context.ts:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: C:\workspace\m7d\svelte-context-enhanced\website\node_modules\@raythurnevoid\svelte-context-enhanced\index.js
require() of ES modules is not supported.
require() of C:\workspace\m7d\svelte-context-enhanced\website\node_modules\@raythurnevoid\svelte-context-enhanced\index.js from C:\workspace\m7d\vite\packages\vite\dist\node\chunks\dep-4058344d.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.

I tried to replace resolve packages with webpack's enhanced-resolve: https://www.npmjs.com/package/enhanced-resolve
Their base code is extremely more hure and complicated than resolve but i've managed to make it work well in Vite: https://github.com/raythurnevoid/vite/commit/95a4f859fa31c4f052f2c3ab422b8f6e82154269

Another upside of enhanced-resolve is that it already supports also "imports" field, that could be a good replace for the numerous "alias" fields of tools like Jest, Rollup, Vite itself and tsconfig paths:
https://nodejs.org/api/packages.html#packages_imports
https://nodejs.org/api/packages.html#packages_subpath_imports

if this fix is feasible i'll open a PR with it.

Reproduction

To reproduce it's enough to import an ESM only package eg: https://github.com/raythurnevoid/strings-filter
Repo example: https://github.com/raythurnevoid/vite-esm-error-reproduction/tree/main

System Info

Output of npx envinfo --system --npmPackages vite,@vitejs/plugin-vue --binaries --browsers:

System:
    OS: Windows 10 10.0.19042
    CPU: (16) x64 AMD Ryzen 9 4900H with Radeon Graphics
    Memory: 16.09 GB / 31.42 GB
  Binaries:
    Node: 16.2.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.10 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 7.13.0 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Spartan (44.19041.1023.0), Chromium (91.0.864.54)
    Internet Explorer: 11.0.19041.1

Used package manager: npm

Logs

shows logs
PS C:\workspace\m7d\vite-esm> npm run dev

> test-ssr-vue@0.0.0 dev
> node server

http://localhost:3000
[@vue/compiler-sfc] <script setup> is still an experimental proposal.
Follow its status at https://github.com/vuejs/rfcs/pull/227.

[@vue/compiler-sfc] When using experimental features,
it is recommended to pin your vue dependencies to exact versions to avoid breakage.

7:35:45 PM [vite] Error when evaluating SSR module /src/pages/Home.vue:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: C:\workspace\m7d\vite-esm\node_modules\@raythurnevoid\strings-filter\index.js
require() of ES modules is not supported.
require() of C:\workspace\m7d\vite-esm\node_modules\@raythurnevoid\strings-filter\index.js from C:\workspace\m7d\vite-esm\node_modules\vite\dist\node\chunks\dep-0ed4fbc0.js is an ES module file as it is a .js file whose nearest parent package.json contains 
"type": "module" which defines all .js files in that package scope as ES modules.
Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from C:\workspace\m7d\vite-esm\node_modules\@raythurnevoid\strings-filter\package.json.

    at new NodeError (node:internal/errors:363:5)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1126:13)
    at Module.load (node:internal/modules/cjs/loader:989:32)
    at Function.Module._load (node:internal/modules/cjs/loader:829:14)
    at Module.require (node:internal/modules/cjs/loader:1013:19)
    at require (node:internal/modules/cjs/helpers:93:18)
    at nodeRequire (C:\workspace\m7d\vite-esm\node_modules\vite\dist\node\chunks\dep-0ed4fbc0.js:69996:17)
    at ssrImport (C:\workspace\m7d\vite-esm\node_modules\vite\dist\node\chunks\dep-0ed4fbc0.js:69949:20)
    at eval (/src/pages/Home.vue:7:31)
    at instantiateModule (C:\workspace\m7d\vite-esm\node_modules\vite\dist\node\chunks\dep-0ed4fbc0.js:69982:166)
[Vue Router warn]: uncaught error during route navigation:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: C:\workspace\m7d\vite-esm\node_modules\@raythurnevoid\strings-filter\index.js
require() of ES modules is not supported.
require() of C:\workspace\m7d\vite-esm\node_modules\@raythurnevoid\strings-filter\index.js from C:\workspace\m7d\vite-esm\node_modules\vite\dist\node\chunks\dep-0ed4fbc0.js is an ES module file as it is a .js file whose nearest parent package.json contains 
"type": "module" which defines all .js files in that package scope as ES modules.
Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from C:\workspace\m7d\vite-esm\node_modules\@raythurnevoid\strings-filter\package.json.

    at new NodeError (node:internal/errors:363:5)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1126:13)
    at Module.load (node:internal/modules/cjs/loader:989:32)
    at Function.Module._load (node:internal/modules/cjs/loader:829:14)
    at Module.require (node:internal/modules/cjs/loader:1013:19)
    at require (node:internal/modules/cjs/helpers:93:18)
    at nodeRequire (C:\workspace\m7d\vite-esm\node_modules\vite\dist\node\chunks\dep-0ed4fbc0.js:69996:17)
    at ssrImport (C:\workspace\m7d\vite-esm\node_modules\vite\dist\node\chunks\dep-0ed4fbc0.js:69949:20)
    at eval (/src/pages/Home.vue:7:31)
    at instantiateModule (C:\workspace\m7d\vite-esm\node_modules\vite\dist\node\chunks\dep-0ed4fbc0.js:69982:166) {
  code: 'ERR_REQUIRE_ESM'
}
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: C:\workspace\m7d\vite-esm\node_modules\@raythurnevoid\strings-filter\index.js
require() of ES modules is not supported.
require() of C:\workspace\m7d\vite-esm\node_modules\@raythurnevoid\strings-filter\index.js from C:\workspace\m7d\vite-esm\node_modules\vite\dist\node\chunks\dep-0ed4fbc0.js is an ES module file as it is a .js file whose nearest parent package.json contains 
"type": "module" which defines all .js files in that package scope as ES modules.
Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from C:\workspace\m7d\vite-esm\node_modules\@raythurnevoid\strings-filter\package.json.

    at new NodeError (node:internal/errors:363:5)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1126:13)
    at Module.load (node:internal/modules/cjs/loader:989:32)
    at Function.Module._load (node:internal/modules/cjs/loader:829:14)
    at Module.require (node:internal/modules/cjs/loader:1013:19)
    at require (node:internal/modules/cjs/helpers:93:18)
    at nodeRequire (C:\workspace\m7d\vite-esm\node_modules\vite\dist\node\chunks\dep-0ed4fbc0.js:69996:17)
    at ssrImport (C:\workspace\m7d\vite-esm\node_modules\vite\dist\node\chunks\dep-0ed4fbc0.js:69949:20)
    at eval (/src/pages/Home.vue:7:31)
    at instantiateModule (C:\workspace\m7d\vite-esm\node_modules\vite\dist\node\chunks\dep-0ed4fbc0.js:69982:166)
node:internal/process/promises:246
          triggerUncaughtException(err, true /* fromPromise */);
          ^

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: C:\workspace\m7d\vite-esm\node_modules\@raythurnevoid\strings-filter\index.js
require() of ES modules is not supported.
require() of C:\workspace\m7d\vite-esm\node_modules\@raythurnevoid\strings-filter\index.js from C:\workspace\m7d\vite-esm\node_modules\vite\dist\node\chunks\dep-0ed4fbc0.js is an ES module file as it is a .js file whose nearest parent package.json contains 
"type": "module" which defines all .js files in that package scope as ES modules.

    at new NodeError (node:internal/errors:363:5)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1126:13)
    at Module.load (node:internal/modules/cjs/loader:989:32)
    at Function.Module._load (node:internal/modules/cjs/loader:829:14)
    at Module.require (node:internal/modules/cjs/loader:1013:19)
    at require (node:internal/modules/cjs/helpers:93:18)
    at ssrImport (C:\workspace\m7d\vite-esm\node_modules\vite\dist\node\chunks\dep-0ed4fbc0.js:69949:20)
    at eval (/src/pages/Home.vue:7:31)
    at instantiateModule (C:\workspace\m7d\vite-esm\node_modules\vite\dist\node\chunks\dep-0ed4fbc0.js:69982:166) {
  code: 'ERR_REQUIRE_ESM'
}

Before submitting the issue, please make sure you do the following

  • Read the Contributing Guidelines.
  • Read the docs.
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • Provide a description in this issue that describes the bug.
  • Make sure this is a Vite issue and not a framework-specific issue. For example, if it's a Vue SFC related bug, it should likely be reported to https://github.com/vuejs/vue-next instead.
  • Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
@aleclarson
Copy link
Member

aleclarson commented Jul 16, 2021

The error message seems to indicate that resolve is not the problem, but rather trying to require a module with ESM syntax. It seems that ESM-only modules need to be transformed before they're required (or use dynamic import instead).

* TODO right now externals are imported using require(), we probably need to
* rework this when more libraries ship native ESM distributions for Node.

And from the docs:

In the future, this heuristics will likely improve to detect if the project has type: "module" enabled, so that Vite can also externalize dependencies that ship Node-compatible ESM builds by importing them via dynamic import() during SSR.

@benmccann
Copy link
Collaborator

Core SvelteKit functionality cannot be used because of this issue: sveltejs/kit#2237. The @sveltejs/kit package is an ESM package with an exports field and Vite doesn't know how to load it

@matthewp
Copy link
Contributor

Snowpack resolved this issue by abstracting to use import() by default: https://github.com/snowpackjs/snowpack/blob/d8cc54a7816faef9d98459a1e24f54912163868b/snowpack/assets/require-or-import.js

@benmccann
Copy link
Collaborator

This is now causing problems for SvelteKit in a second way. Svelte exports different code on the client and server, but we always get the client-side version because resolve is broken: browserify/resolve#222.

@Niputi
Copy link
Contributor

Niputi commented Sep 23, 2021

maybe this module could be of use for a implementation https://github.com/unjs/mlly

@benmccann
Copy link
Collaborator

https://www.npmjs.com/package/enhanced-resolve might be another alternative. It's used by webpack, so should be fairly battle-tested

benmccann referenced this issue in sveltejs/vite-plugin-svelte Sep 23, 2021
@benmccann benmccann added p4-important Violate documented behavior or significantly improves performance (priority) and removed p3-minor-bug An edge case that only affects very specific usage (priority) labels Oct 1, 2021
@benmccann
Copy link
Collaborator

benmccann commented Oct 1, 2021

Here's a branch with enhanced-resolve: main...benmccann:enhanced-resolve

It's a pretty small change and seems to basically work. Some of the tests are failing though. I don't know that I'll have time to look into it, but thought I'd share in case it helps anyone who might want to give it a try

Edit: I didn't see, but it looks like there was also a proposal to make this change above. That version might work better, but I haven't tested yet: https://github.com/raythurnevoid/vite/commit/95a4f859fa31c4f052f2c3ab422b8f6e82154269

@benmccann
Copy link
Collaborator

I just tested @raythurnevoid's example from the issue description and it works now with Vite 2.7 except for one issue. The code looks like:

export * from "./classList";
export * from "./styleList";
export * from "./filterStrings";
export * from "./customList";
export * from "./types";

To get it to work I had to change it to:

export * from "./classList.js";
export * from "./styleList.js";
export * from "./filterStrings.js";
export * from "./customList.js";
export * from "./types.js";

I think that's working as intended though and is a bug in @raythurnevoid's example: https://stackoverflow.com/a/64242299

@benmccann
Copy link
Collaborator

This still doesn't work with https://github.com/Karlinator/reproduction-sveltekit-hooks when @sveltejs/kit is added to ssr/external

@benmccann benmccann added p2-edge-case Bug, but has workaround or limited in scope (priority) and removed p4-important Violate documented behavior or significantly improves performance (priority) labels Nov 8, 2021
@benmccann
Copy link
Collaborator

It looks like @raythurnevoid and I had figured out different pieces of this. I combined our two solutions and sent a PR for it: #5593

@benmccann
Copy link
Collaborator

This would also be fixed by #3951

@frandiox
Copy link
Contributor

@aleclarson Can we close this one? 🤔

@github-actions github-actions bot locked and limited conversation to collaborators Dec 7, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feat: ssr p2-edge-case Bug, but has workaround or limited in scope (priority)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants