Describe the bug
Discovered thanks to this bug report to vite-plugin-cjs-interop.
When a prebundled CommonJS dependency is used before its import statement in source code, a Cannot access '<binding>' before initialization error is thrown in the browser in dev. This happens because the CJS interop const assignment is not hoisted to the top of the module along with the import declaration.
Per the ES module spec, import declarations are hoisted, so using an imported binding before the import statement should be valid.
For example, this source:
console.log(ms("2 days"));
import ms from "ms";
Is transformed by Vite's dev server into:
console.log(ms("2 days"));
import __vite__cjsImport0_ms from "/node_modules/.vite/deps/ms.js?v=5b7f195e";
const ms = __vite__cjsImport0_ms; // ← This should be hoisted to the top!
The import is hoisted by the browser but const ms is not, so ms is in the TDZ when console.log(ms("2 days")) executes.
This only affects CJS dependencies. ESM dependencies work correctly.
Reproduction
https://github.com/cyco130/vite-import-hoist-bug-repro
Steps to reproduce
git clone https://github.com/cyco130/vite-import-hoist-bug-repro.git
cd vite-import-hoist-bug-repro
pnpm install
pnpm dev
Then visit http://localhost:5173 and click "CJS (broken)" and check the browser console for the error.
System Info
System:
OS: macOS 26.3.1
CPU: (10) arm64 Apple M1 Max
Memory: 9.51 GB / 64.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 22.22.1 - /usr/local/bin/node
npm: 10.9.4 - /usr/local/bin/npm
pnpm: 10.33.0 - /Users/fatih/Library/pnpm/pnpm
bun: 1.3.11 - /Users/fatih/.bun/bin/bun
Deno: 2.7.1 - /opt/homebrew/bin/deno
Browsers:
Chrome: 146.0.7680.178
Firefox: 149.0
Safari: 26.3.1
npmPackages:
vite: ^8.0.3 => 8.0.3
Used Package Manager
pnpm
Logs
; Snipped the config, none was involved
vite:deps (client) removing old cache dir /private/tmp/vite-import-hoist-bug-repro/node_modules/.vite/deps +0ms
vite:deps scanning for dependencies... +0ms
vite:deps Crawling dependencies using entries:
vite:deps /private/tmp/vite-import-hoist-bug-repro/cjs.html
vite:deps /private/tmp/vite-import-hoist-bug-repro/esm.html
vite:deps /private/tmp/vite-import-hoist-bug-repro/index.html +0ms
VITE v8.0.3 ready in 114 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h + enter to show help
vite:resolve 0.45ms /cjs.js -> /private/tmp/vite-import-hoist-bug-repro/cjs.js +0ms
vite:resolve 0.51ms /esm.js -> /private/tmp/vite-import-hoist-bug-repro/esm.js +0ms
vite:resolve 0.29ms parse-ms -> /private/tmp/vite-import-hoist-bug-repro/node_modules/.pnpm/[email protected]/node_modules/parse-ms/index.js +1ms
vite:resolve 0.36ms ms -> /private/tmp/vite-import-hoist-bug-repro/node_modules/.pnpm/[email protected]/node_modules/ms/index.js +0ms
vite:deps Scan completed in 13.32ms:
vite:deps ms -> /private/tmp/vite-import-hoist-bug-repro/node_modules/.pnpm/[email protected]/node_modules/ms/index.js
vite:deps parse-ms -> /private/tmp/vite-import-hoist-bug-repro/node_modules/.pnpm/[email protected]/node_modules/parse-ms/index.js +11ms
vite:deps creating package.json in /private/tmp/vite-import-hoist-bug-repro/node_modules/.vite/deps_temp_9737eff9 +15ms
vite:deps Dependencies bundled in 6.06ms +6ms
vite:deps ✨ static imports crawl ended +51ms
vite:deps ✨ using post-scan optimizer result, the scanner found every used dependency +1ms
vite:deps creating metadata.json in /private/tmp/vite-import-hoist-bug-repro/node_modules/.vite/deps_temp_9737eff9 +31ms
vite:deps renaming /private/tmp/vite-import-hoist-bug-repro/node_modules/.vite/deps_temp_9737eff9 to /private/tmp/vite-import-hoist-bug-repro/node_modules/.vite/deps +0ms
vite:deps ✨ dependencies optimized +0ms
vite:html-fallback Rewriting GET / to /index.html +0ms
vite:time 13.52ms /index.html +0ms
vite:resolve 1.37ms /@vite/client -> /private/tmp/vite-import-hoist-bug-repro/node_modules/.pnpm/[email protected]@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/client.mjs +25s
vite:load 1.51ms [fs] /@vite/client +0ms
vite:resolve 0.97ms @vite/env -> /private/tmp/vite-import-hoist-bug-repro/node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/env.mjs +8ms
vite:import-analysis 3.70ms [1 imports rewritten] node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/client.mjs +0ms
vite:transform 5.67ms /@vite/client +0ms
vite:time 26.27ms /@vite/client +37ms
vite:load 14.50ms [fs] /node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/env.mjs +22ms
vite:import-analysis 0.04ms [no imports] node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/env.mjs +15ms
vite:transform 0.58ms /node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/env.mjs +15ms
vite:cache [304] /node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/env.mjs +0ms
vite:time 0.08ms /node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/env.mjs +5ms
vite:html-fallback Rewriting GET /cjs.html to /cjs.html +2s
vite:time 5.70ms /cjs.html +2s
vite:load 0.70ms [fs] /cjs.js +2s
vite:resolve 0.23ms ms -> /private/tmp/vite-import-hoist-bug-repro/node_modules/.vite/deps/ms.js?v=bb49fb15 +2s
vite:import-analysis /node_modules/.vite/deps/ms.js?v=bb49fb15 needs interop +2s
vite:import-analysis 1.59ms [1 imports rewritten] cjs.js +1ms
vite:transform 1.99ms /cjs.js +2s
vite:optimize-deps load /private/tmp/vite-import-hoist-bug-repro/node_modules/.vite/deps/ms.js +0ms
vite:load 1.17ms [plugin] /node_modules/.vite/deps/ms.js?v=bb49fb15 +3ms
vite:import-analysis 0.24ms [no imports] node_modules/.vite/deps/ms.js?v=bb49fb15 +2ms
vite:transform 1.03ms [skipped] /node_modules/.vite/deps/ms.js?v=bb49fb15 +2ms
vite:cache [memory] /@vite/client +0ms
vite:time 0.21ms /@vite/client +19ms
vite:cache [memory] /cjs.js +1ms
vite:time 0.63ms /cjs.js +1ms
vite:cache [304] /node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/env.mjs +2s
vite:time 0.20ms /node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/env.mjs +1ms
vite:cache [memory] /node_modules/.vite/deps/ms.js?v=bb49fb15 +3ms
vite:time 0.34ms /node_modules/.vite/deps/ms.js?v=bb49fb15 +2ms
vite:html-fallback Rewriting GET /.well-known/appspecific/com.chrome.devtools.json to /index.html +5s
vite:time 3.95ms /index.html +5s
vite:time 0.87ms /node_modules/.vite/deps/ms.js.map +13ms
vite:html-fallback Rewriting GET /cjs.html to /cjs.html +921ms
vite:cache [memory] /cjs.js +6s
vite:time 1.35ms /cjs.html +907ms
vite:html-fallback Rewriting GET /.well-known/appspecific/com.chrome.devtools.json to /index.html +14ms
vite:cache [memory] /@vite/client +13ms
vite:time 6.83ms /@vite/client +20ms
vite:cache [memory] /cjs.js +9ms
vite:time 0.90ms /cjs.js +3ms
vite:time 12.07ms /index.html +1ms
vite:cache [memory] /node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/env.mjs +8ms
vite:time 0.34ms /node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/env.mjs +6ms
vite:cache [memory] /node_modules/.vite/deps/ms.js?v=bb49fb15 +1ms
vite:time 0.15ms /node_modules/.vite/deps/ms.js?v=bb49fb15 +1ms
vite:time 1.16ms /node_modules/.vite/deps/ms.js.map +9ms
Validations
Describe the bug
When a prebundled CommonJS dependency is used before its
importstatement in source code, aCannot access '<binding>' before initializationerror is thrown in the browser in dev. This happens because the CJS interopconstassignment is not hoisted to the top of the module along with theimportdeclaration.Per the ES module spec,
importdeclarations are hoisted, so using an imported binding before theimportstatement should be valid.For example, this source:
Is transformed by Vite's dev server into:
The
importis hoisted by the browser butconst msis not, somsis in the TDZ whenconsole.log(ms("2 days"))executes.This only affects CJS dependencies. ESM dependencies work correctly.
Reproduction
https://github.com/cyco130/vite-import-hoist-bug-repro
Steps to reproduce
git clone https://github.com/cyco130/vite-import-hoist-bug-repro.git cd vite-import-hoist-bug-repro pnpm install pnpm devThen visit http://localhost:5173 and click "CJS (broken)" and check the browser console for the error.
System Info
System: OS: macOS 26.3.1 CPU: (10) arm64 Apple M1 Max Memory: 9.51 GB / 64.00 GB Shell: 5.9 - /bin/zsh Binaries: Node: 22.22.1 - /usr/local/bin/node npm: 10.9.4 - /usr/local/bin/npm pnpm: 10.33.0 - /Users/fatih/Library/pnpm/pnpm bun: 1.3.11 - /Users/fatih/.bun/bin/bun Deno: 2.7.1 - /opt/homebrew/bin/deno Browsers: Chrome: 146.0.7680.178 Firefox: 149.0 Safari: 26.3.1 npmPackages: vite: ^8.0.3 => 8.0.3Used Package Manager
pnpm
Logs
; Snipped the config, none was involved
vite:deps (client) removing old cache dir /private/tmp/vite-import-hoist-bug-repro/node_modules/.vite/deps +0ms
vite:deps scanning for dependencies... +0ms
vite:deps Crawling dependencies using entries:
vite:deps /private/tmp/vite-import-hoist-bug-repro/cjs.html
vite:deps /private/tmp/vite-import-hoist-bug-repro/esm.html
vite:deps /private/tmp/vite-import-hoist-bug-repro/index.html +0ms
VITE v8.0.3 ready in 114 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h + enter to show help
vite:resolve 0.45ms /cjs.js -> /private/tmp/vite-import-hoist-bug-repro/cjs.js +0ms
vite:resolve 0.51ms /esm.js -> /private/tmp/vite-import-hoist-bug-repro/esm.js +0ms
vite:resolve 0.29ms parse-ms -> /private/tmp/vite-import-hoist-bug-repro/node_modules/.pnpm/[email protected]/node_modules/parse-ms/index.js +1ms
vite:resolve 0.36ms ms -> /private/tmp/vite-import-hoist-bug-repro/node_modules/.pnpm/[email protected]/node_modules/ms/index.js +0ms
vite:deps Scan completed in 13.32ms:
vite:deps ms -> /private/tmp/vite-import-hoist-bug-repro/node_modules/.pnpm/[email protected]/node_modules/ms/index.js
vite:deps parse-ms -> /private/tmp/vite-import-hoist-bug-repro/node_modules/.pnpm/[email protected]/node_modules/parse-ms/index.js +11ms
vite:deps creating package.json in /private/tmp/vite-import-hoist-bug-repro/node_modules/.vite/deps_temp_9737eff9 +15ms
vite:deps Dependencies bundled in 6.06ms +6ms
vite:deps ✨ static imports crawl ended +51ms
vite:deps ✨ using post-scan optimizer result, the scanner found every used dependency +1ms
vite:deps creating metadata.json in /private/tmp/vite-import-hoist-bug-repro/node_modules/.vite/deps_temp_9737eff9 +31ms
vite:deps renaming /private/tmp/vite-import-hoist-bug-repro/node_modules/.vite/deps_temp_9737eff9 to /private/tmp/vite-import-hoist-bug-repro/node_modules/.vite/deps +0ms
vite:deps ✨ dependencies optimized +0ms
vite:html-fallback Rewriting GET / to /index.html +0ms
vite:time 13.52ms /index.html +0ms
vite:resolve 1.37ms /@vite/client -> /private/tmp/vite-import-hoist-bug-repro/node_modules/.pnpm/[email protected]@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/client.mjs +25s
vite:load 1.51ms [fs] /@vite/client +0ms
vite:resolve 0.97ms @vite/env -> /private/tmp/vite-import-hoist-bug-repro/node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/env.mjs +8ms
vite:import-analysis 3.70ms [1 imports rewritten] node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/client.mjs +0ms
vite:transform 5.67ms /@vite/client +0ms
vite:time 26.27ms /@vite/client +37ms
vite:load 14.50ms [fs] /node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/env.mjs +22ms
vite:import-analysis 0.04ms [no imports] node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/env.mjs +15ms
vite:transform 0.58ms /node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/env.mjs +15ms
vite:cache [304] /node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/env.mjs +0ms
vite:time 0.08ms /node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/env.mjs +5ms
vite:html-fallback Rewriting GET /cjs.html to /cjs.html +2s
vite:time 5.70ms /cjs.html +2s
vite:load 0.70ms [fs] /cjs.js +2s
vite:resolve 0.23ms ms -> /private/tmp/vite-import-hoist-bug-repro/node_modules/.vite/deps/ms.js?v=bb49fb15 +2s
vite:import-analysis /node_modules/.vite/deps/ms.js?v=bb49fb15 needs interop +2s
vite:import-analysis 1.59ms [1 imports rewritten] cjs.js +1ms
vite:transform 1.99ms /cjs.js +2s
vite:optimize-deps load /private/tmp/vite-import-hoist-bug-repro/node_modules/.vite/deps/ms.js +0ms
vite:load 1.17ms [plugin] /node_modules/.vite/deps/ms.js?v=bb49fb15 +3ms
vite:import-analysis 0.24ms [no imports] node_modules/.vite/deps/ms.js?v=bb49fb15 +2ms
vite:transform 1.03ms [skipped] /node_modules/.vite/deps/ms.js?v=bb49fb15 +2ms
vite:cache [memory] /@vite/client +0ms
vite:time 0.21ms /@vite/client +19ms
vite:cache [memory] /cjs.js +1ms
vite:time 0.63ms /cjs.js +1ms
vite:cache [304] /node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/env.mjs +2s
vite:time 0.20ms /node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/env.mjs +1ms
vite:cache [memory] /node_modules/.vite/deps/ms.js?v=bb49fb15 +3ms
vite:time 0.34ms /node_modules/.vite/deps/ms.js?v=bb49fb15 +2ms
vite:html-fallback Rewriting GET /.well-known/appspecific/com.chrome.devtools.json to /index.html +5s
vite:time 3.95ms /index.html +5s
vite:time 0.87ms /node_modules/.vite/deps/ms.js.map +13ms
vite:html-fallback Rewriting GET /cjs.html to /cjs.html +921ms
vite:cache [memory] /cjs.js +6s
vite:time 1.35ms /cjs.html +907ms
vite:html-fallback Rewriting GET /.well-known/appspecific/com.chrome.devtools.json to /index.html +14ms
vite:cache [memory] /@vite/client +13ms
vite:time 6.83ms /@vite/client +20ms
vite:cache [memory] /cjs.js +9ms
vite:time 0.90ms /cjs.js +3ms
vite:time 12.07ms /index.html +1ms
vite:cache [memory] /node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/env.mjs +8ms
vite:time 0.34ms /node_modules/.pnpm/vite@8.0.3_@emnapi+core@1.9.2_@emnapi[email protected]/node_modules/vite/dist/client/env.mjs +6ms
vite:cache [memory] /node_modules/.vite/deps/ms.js?v=bb49fb15 +1ms
vite:time 0.15ms /node_modules/.vite/deps/ms.js?v=bb49fb15 +1ms
vite:time 1.16ms /node_modules/.vite/deps/ms.js.map +9ms
Validations