vitejs / vite

Next generation frontend tooling. It's fast!
http://vite.dev
MIT License
67.84k stars 6.11k forks source link

“Unexpected early exit” when building with Node 20 and Yarn PnP #13106

Closed marvinruder closed 1 year ago

marvinruder commented 1 year ago

Describe the bug

Initiating a build in the MWE repository via yarn build results in the following error, after which the build fails:

Unexpected early exit. This happens when Promises returned by plugins cannot resolve. Unfinished hook action(s) on exit:
(vite:build-html) transform "/workspaces/vite-project/index.html"
error during build:
Error: Unexpected early exit. This happens when Promises returned by plugins cannot resolve. Unfinished hook action(s) on exit:
(vite:build-html) transform "/workspaces/vite-project/index.html"
    at EventEmitter.handleEmptyEventLoop (file:///workspaces/vite-project/.yarn/cache/rollup-npm-3.21.5-a57d6eed06-dfe2e4002f.zip/node_modules/rollup/dist/es/shared/node-entry.js:24909:20)
    at Object.onceWrapper (node:events:625:28)
    at EventEmitter.emit (node:events:511:28)
    at process.<anonymous> (file:///workspaces/vite-project/.yarn/cache/rollup-npm-3.21.5-a57d6eed06-dfe2e4002f.zip/node_modules/rollup/dist/es/shared/node-entry.js:24903:55)
    at process.emit (node:events:523:35)
    at process.emit (/workspaces/vite-project/.pnp.cjs:10322:25)

Reproduction

https://github.com/marvinruder/vite-project

Steps to reproduce

  1. Clone the repository (or use GitHub Codespaces to ensure a consistent environment)
  2. Run nvm install 20 and ensure that node -v shows that the Node version is v20.x.x
  3. Run yarn
  4. Run yarn build and observe the error message shown above

System Info

(on GitHub Codespaces)

  System:
    OS: Linux 5.4 Ubuntu 20.04.6 LTS (Focal Fossa)
    CPU: (2) x64 Intel(R) Xeon(R) Platinum 8272CL CPU @ 2.60GHz
    Memory: 2.53 GB / 3.84 GB
    Container: Yes
    Shell: 5.0.17 - /bin/bash
  Binaries:
    Node: 20.1.0 - ~/nvm/current/bin/node
    Yarn: 3.5.1 - /usr/bin/yarn
    npm: 9.6.4 - ~/nvm/current/bin/npm

(on macOS)

  System:
    OS: macOS 13.4
    CPU: (8) arm64 Apple M1
    Memory: 1.48 GB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.1.0 - ~/.nvm/versions/node/v20.1.0/bin/node
    Yarn: 3.5.1 - ~/.nvm/versions/node/v20.1.0/bin/yarn
    npm: 9.6.4 - ~/.nvm/versions/node/v20.1.0/bin/npm
  Browsers:
    Chrome: 112.0.5615.137
    Firefox: 111.0.1
    Safari: 16.5

(on Jenkins)

  System:
    OS: Linux 6.2 Alpine Linux
    CPU: (4) x64 AMD EPYC 7282 16-Core Processor
    Memory: 4.37 GB / 7.74 GB
    Container: Yes
    Shell: 1.35.0 - /bin/ash
  Binaries:
    Node: 20.1.0 - /usr/local/bin/node
    Yarn: 3.5.1 - /usr/local/bin/yarn
    npm: 9.6.4 - /usr/local/bin/npm

Used Package Manager

yarn

Logs

Click to expand ```shell vite:config no config file found. +0ms vite:config using resolved config: { vite:config root: '/workspaces/vite-project', vite:config base: '/', vite:config mode: 'production', vite:config configFile: undefined, vite:config logLevel: undefined, vite:config clearScreen: undefined, vite:config optimizeDeps: { vite:config disabled: 'build', vite:config force: undefined, vite:config esbuildOptions: { preserveSymlinks: false } vite:config }, vite:config build: { vite:config target: [ 'es2020', 'edge88', 'firefox78', 'chrome87', 'safari14' ], vite:config cssTarget: [ 'es2020', 'edge88', 'firefox78', 'chrome87', 'safari14' ], vite:config outDir: 'dist', vite:config assetsDir: 'assets', vite:config assetsInlineLimit: 4096, vite:config cssCodeSplit: true, vite:config sourcemap: false, vite:config rollupOptions: {}, vite:config minify: 'esbuild', vite:config terserOptions: {}, vite:config write: true, vite:config emptyOutDir: null, vite:config copyPublicDir: true, vite:config manifest: false, vite:config lib: false, vite:config ssr: false, vite:config ssrManifest: false, vite:config ssrEmitAssets: false, vite:config reportCompressedSize: true, vite:config chunkSizeWarningLimit: 500, vite:config watch: null, vite:config commonjsOptions: { include: [Array], extensions: [Array] }, vite:config dynamicImportVarsOptions: { warnOnError: true, exclude: [Array] }, vite:config modulePreload: { polyfill: true }, vite:config cssMinify: true vite:config }, vite:config configFileDependencies: [], vite:config inlineConfig: { vite:config root: undefined, vite:config base: undefined, vite:config mode: undefined, vite:config configFile: undefined, vite:config logLevel: undefined, vite:config clearScreen: undefined, vite:config optimizeDeps: { force: undefined }, vite:config build: {} vite:config }, vite:config rawBase: '/', vite:config resolve: { vite:config mainFields: [ 'module', 'jsnext:main', 'jsnext' ], vite:config browserField: true, vite:config conditions: [], vite:config extensions: [ vite:config '.mjs', '.js', vite:config '.mts', '.ts', vite:config '.jsx', '.tsx', vite:config '.json' vite:config ], vite:config dedupe: [], vite:config preserveSymlinks: false, vite:config alias: [ [Object], [Object] ] vite:config }, vite:config publicDir: '/workspaces/vite-project/public', vite:config cacheDir: '/workspaces/vite-project/node_modules/.vite', vite:config command: 'build', vite:config ssr: { vite:config format: 'esm', vite:config target: 'node', vite:config optimizeDeps: { disabled: true, esbuildOptions: [Object] } vite:config }, vite:config isWorker: false, vite:config mainConfig: null, vite:config isProduction: true, vite:config plugins: [ vite:config 'vite:build-metadata', vite:config 'vite:watch-package-data', vite:config 'vite:pre-alias', vite:config 'alias', vite:config 'vite:modulepreload-polyfill', vite:config 'vite:resolve', vite:config 'vite:html-inline-proxy', vite:config 'vite:css', vite:config 'vite:esbuild', vite:config 'vite:json', vite:config 'vite:wasm-helper', vite:config 'vite:worker', vite:config 'vite:asset', vite:config 'vite:wasm-fallback', vite:config 'vite:define', vite:config 'vite:css-post', vite:config 'vite:build-html', vite:config 'vite:worker-import-meta-url', vite:config 'vite:asset-import-meta-url', vite:config 'vite:force-systemjs-wrap-complete', vite:config 'commonjs', vite:config 'vite:data-uri', vite:config 'vite:dynamic-import-vars', vite:config 'vite:import-glob', vite:config 'vite:build-import-analysis', vite:config 'vite:esbuild-transpile', vite:config 'vite:terser', vite:config 'vite:reporter', vite:config 'vite:load-fallback' vite:config ], vite:config esbuild: { jsxDev: false }, vite:config server: { vite:config preTransformRequests: true, vite:config sourcemapIgnoreList: [Function: isInNodeModules], vite:config middlewareMode: false, vite:config fs: { strict: true, allow: [Array], deny: [Array] } vite:config }, vite:config preview: { vite:config port: undefined, vite:config strictPort: undefined, vite:config host: undefined, vite:config https: undefined, vite:config open: undefined, vite:config proxy: undefined, vite:config cors: undefined, vite:config headers: undefined vite:config }, vite:config envDir: '/workspaces/vite-project', vite:config env: { BASE_URL: '/', MODE: 'production', DEV: false, PROD: true }, vite:config assetsInclude: [Function: assetsInclude], vite:config logger: { vite:config hasWarned: false, vite:config info: [Function: info], vite:config warn: [Function: warn], vite:config warnOnce: [Function: warnOnce], vite:config error: [Function: error], vite:config clearScreen: [Function: clearScreen], vite:config hasErrorLogged: [Function: hasErrorLogged] vite:config }, vite:config packageCache: Map(1) { vite:config 'fnpd_/workspaces/vite-project' => { vite:config dir: '/workspaces/vite-project', vite:config data: [Object], vite:config hasSideEffects: [Function: hasSideEffects], vite:config webResolvedImports: {}, vite:config nodeResolvedImports: {}, vite:config setResolvedCache: [Function: setResolvedCache], vite:config getResolvedCache: [Function: getResolvedCache] vite:config }, vite:config set: [Function (anonymous)] vite:config }, vite:config createResolver: [Function: createResolver], vite:config worker: { vite:config format: 'iife', vite:config plugins: [ vite:config 'vite:build-metadata', vite:config 'vite:watch-package-data', vite:config 'vite:pre-alias', vite:config 'alias', vite:config 'vite:modulepreload-polyfill', vite:config 'vite:resolve', vite:config 'vite:html-inline-proxy', vite:config 'vite:css', vite:config 'vite:esbuild', vite:config 'vite:json', vite:config 'vite:wasm-helper', vite:config 'vite:worker', vite:config 'vite:asset', vite:config 'vite:wasm-fallback', vite:config 'vite:define', vite:config 'vite:css-post', vite:config 'vite:build-html', vite:config 'vite:worker-import-meta-url', vite:config 'vite:asset-import-meta-url', vite:config 'vite:force-systemjs-wrap-complete', vite:config 'commonjs', vite:config 'vite:data-uri', vite:config 'vite:worker-post', vite:config 'vite:dynamic-import-vars', vite:config 'vite:import-glob', vite:config 'vite:build-import-analysis', vite:config 'vite:esbuild-transpile', vite:config 'vite:terser', vite:config 'vite:load-fallback' vite:config ], vite:config rollupOptions: {}, vite:config getSortedPlugins: [Function: getSortedPlugins], vite:config getSortedPluginHooks: [Function: getSortedPluginHooks] vite:config }, vite:config appType: 'spa', vite:config experimental: { importGlobRestoreExtension: false, hmrPartialAccept: false }, vite:config getSortedPlugins: [Function: getSortedPlugins], vite:config getSortedPluginHooks: [Function: getSortedPluginHooks] vite:config } +10ms vite v4.3.5 building for production... vite:esbuild 27.44ms tsconfck init /workspaces/vite-project +0ms Unexpected early exit. This happens when Promises returned by plugins cannot resolve. Unfinished hook action(s) on exit: (vite:build-html) transform "/workspaces/vite-project/index.html" error during build: Error: Unexpected early exit. This happens when Promises returned by plugins cannot resolve. Unfinished hook action(s) on exit: (vite:build-html) transform "/workspaces/vite-project/index.html" at EventEmitter.handleEmptyEventLoop (file:///workspaces/vite-project/.yarn/cache/rollup-npm-3.21.5-a57d6eed06-dfe2e4002f.zip/node_modules/rollup/dist/es/shared/node-entry.js:24909:20) at Object.onceWrapper (node:events:625:28) at EventEmitter.emit (node:events:511:28) at process. (file:///workspaces/vite-project/.yarn/cache/rollup-npm-3.21.5-a57d6eed06-dfe2e4002f.zip/node_modules/rollup/dist/es/shared/node-entry.js:24903:55) at process.emit (node:events:523:35) at process.emit (/workspaces/vite-project/.pnp.cjs:10322:25) ```

Validations

marvinruder commented 1 year ago

Perhaps https://github.com/vitejs/vite/issues/13018 is related?

Braunson commented 1 year ago

I'm having a very similar issue of all of a sudden, looks like Vite is filling the SWAP file in WSL until it OOM and the Vite process returns

Fatal process OOM in Failed to reserve virtual memory for CodeRange 
sun0day commented 1 year ago

The reproduction works fine with same versions of node, yarn, npm in my macos.

marvinruder commented 1 year ago

@sun0day For me it sometimes works on my Mac, oftentimes it does not. Same for my CI/CD pipeline. I suspect some kind of race condition, which is difficult to reproduce. Did you try it in GitHub Codespaces? I couldn’t get yarn berry to work in Stackblitz for some reason.

marvinruder commented 1 year ago

Also, I feel that running yarn build (with that script defined as vite build) instead of vite build directly reproduces the error more consistently.

sun0day commented 1 year ago

@sun0day For me it sometimes works on my Mac, oftentimes it does not. Same for my CI/CD pipeline. I suspect some kind of race condition, which is difficult to reproduce. Did you try it in GitHub Codespaces? I couldn’t get yarn berry to work in Stackblitz for some reason.

Ah, I reproduced it. It's more like an issue of yarn@3.5.1 not vite. The code hung in

https://github.com/vitejs/vite/blob/c63ba3fa08a64d75bfffa6885dc4c44875b9c5ba/packages/vite/src/node/plugins/html.ts#L173

marvinruder commented 1 year ago

Ah, I wasn’t sure where to report this, as I could take away either Node 20 or Yarn PnP and the issue would disappear.

Any idea on what exactly is wrong with yarn, so I can report it there? I tried to analyze, but setting too many breakpoints slows down the process so much that the issue disappears and the build simply succeeds (perhaps because the promise could resolve under those conditions only?).

sapphi-red commented 1 year ago

Yarn PnP relies on Custom ESM loader and Custom ESM loader's internals has changed largely from Node v20. So if it's hangs at the dynamic import, I guess it's an issue on Node.js or yarn.

merceyz commented 1 year ago

I'm having a very similar issue of all of a sudden, looks like Vite is filling the SWAP file in WSL until it OOM and the Vite process returns

Fatal process OOM in Failed to reserve virtual memory for CodeRange 

@Braunson You might be running into https://github.com/nodejs/node/issues/47566, have you tried with Node.js v20.1?

Braunson commented 1 year ago

@merceyz I resolved my issue. I'm using the latest Node 16.16.0 (LTS), the latest Yarn. My fix was to delete node_modules/ folder, and run yarn cache clean then yarn. After that the issue went away. Hope it helps you.

marvinruder commented 1 year ago

Just found #nodejs/47929 – is that maybe the same issue here?

marvinruder commented 1 year ago

Appears to be fixed in Node 20.2.