Skip to content

Better handling of dynamic imports in dead code #5676

@blckngm

Description

@blckngm

Describe the bug

When working with SSR, one would expect patterns like this to work:

if (import.meta.env.SSR) {
  const { data } = await import('./loadServer');
  console.log(data);
} else {
  const data = await fetch('/data').then((r) => r.text());
  console.log(data);
}

I.e., ignore loadServer for the browser bundle. It actually works fine with the dev server, but when loadServer (transitively) imports node builtin modules, vite build fails with e.g.:

Error: 'readFile' is not exported by __vite-browser-external, imported by loadServer.js

It would be nice if vite could just figure out that loadServer will never be needed for the browser bundle, and don't try to analyze/resolve code in it. It would also make dev and build behavior more consistent and might perform better in some cases.

I also tried this with esbuild and it does just ignore loadServer in this case:

❯ npx esbuild --format=esm --bundle main.js --define:import.meta.env.SSR=false
// main.js
if (false) {
  const { data } = await null;
  console.log(data);
} else {
  const data = await fetch("/data").then((r) => r.text());
  console.log(data);
}

Reproduction

https://stackblitz.com/edit/vitejs-vite-ts9jc6?devtoolsheight=33&file=main.js

System Info

System:
    OS: Linux undefined
    CPU: (4) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: Unknown - /bin/jsh
  Binaries:
    Node: 14.16.0 - /usr/local/bin/node
    Yarn: 1.22.10 - /bin/yarn
    npm: 7.17.0 - /bin/npm
  npmPackages:
    vite: ^2.6.13 => 2.6.14

Used Package Manager

npm

Logs

No response

Validations

Metadata

Metadata

Assignees

No one assigned

    Labels

    has workaroundp3-minor-bugAn edge case that only affects very specific usage (priority)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions