question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Vite tries to aggressively prebundle even things that won't get used in the browser, and confuses itself

See original GitHub issue

Describe the bug Any import()s in an isomorphic part of the app are aggressively prebundled by Vite, even if they’re never ultimately used in the browser (and even if they are inside an if (!browser) { }). This is a problem because when something cannot successfully be prebundled (e.g., if it uses Node APIs with no browser analogue), something within Vite crashes(?) or gets into a bad state, and - even if the offending import() is removed - Vite then does not perform other prebundling that actually is necessary until the server is restarted. This can lead to, for example, imports of CJS modules being left as import ... from '/node_modules/foo/...', which means the browser is being served CJS files when it is expecting ESM files.

Logs The logs from Vite when it’s failing to prebundle the package look like, e.g.:

 > node_modules/@sentry/node/esm/parsers.js:2:9: error: No matching export in "browser-external:fs" for import "readFile"
    2 │ import { readFile } from 'fs';
      ╵          ~~~~~~~~

 > node_modules/@sentry/node/esm/integrations/utils/http.js:3:9: error: No matching export in "browser-external:url" for import "URL"
    3 │ import { URL } from 'url';
      ╵          ~~~

 > node_modules/@sentry/node/esm/integrations/modules.js:2:9: error: No matching export in "browser-external:fs" for import "existsSync"
    2 │ import { existsSync, readFileSync } from 'fs';
      ╵          ~~~~~~~~~~

 > node_modules/@sentry/node/esm/integrations/modules.js:2:21: error: No matching export in "browser-external:fs" for import "readFileSync"
    2 │ import { existsSync, readFileSync } from 'fs';
      ╵                      ~~~~~~~~~~~~

 > node_modules/@sentry/node/esm/integrations/modules.js:3:9: error: No matching export in "browser-external:path" for import "dirname"
    3 │ import { dirname, join } from 'path';
      ╵          ~~~~~~~

 > node_modules/@sentry/node/esm/integrations/modules.js:3:18: error: No matching export in "browser-external:path" for import "join"
    3 │ import { dirname, join } from 'path';
      ╵                   ~~~~

The logs from the browser when it’s attempting to load the CJS version of a module as a ESM when Vite gives up and serves that instead look like:

Uncaught (in promise) ReferenceError: exports is not defined
    <anonymous> http://localhost:3000/node_modules/decoders/index.js:3

To Reproduce My reproduction uses two of the libraries I was seeing this with in a real project. @sentry/node is the library that can’t (and shouldn’t) be bundled for the browser. decoders is the library that’s available only in CJS and that needs to be prebundled for the browser to understand it.

Clone https://github.com/Conduitry-Repros/kit-1570 and run npm install.

Start up the server with npm run dev and check the browser console, where you should see the results of console.log(await import('decoders'));.

Then, open src/routes/index.svelte and uncomment the indicated line. Refresh the browser if necessary. In the Vite console, you should now see errors about not being able to process @sentry/node. In the browser console, you should see errors that result from attempting to load CJS as ESM. If you look in the network tab, you’ll see that http://localhost:3000/node_modules/decoders/index.js is being requested (the raw CJS version from the package) rather than the http://localhost:3000/node_modules/.vite/decoders.js you should be getting.

This broken state persists even if you re-comment the import('@sentry/node'). You don’t get the prebundled version of decoders again until you restart the server.

Expected behavior A clear and concise description of what you expected to happen.

Stacktraces n/a

Information about your SvelteKit Installation:

Diagnostics
  • The envinfo command hangs for me, I’m guessing because of WSL. This is a separate issue to be looked into, probably.
  • Firefox 88.0.1, but this shouldn’t be relevant
  • No adapter, for now. This is in dev mode.

Severity Fairly severe, as it was causing some very confusing behavior. I do have a workaround for now though, which is to use a helper function that I call instead of import():

export default async function serverImport(id) {
    const { createRequire } = await import('module');
    const require = createRequire('/absolute/path/package.json');
    return require(id);
}

This relies on a known absolute path to resolve relative to, which is fine in my case as I’m using Docker. Note that I cannot use import.meta.url as that is a path that looks absolute but is in fact relative to the root of my project. It’s /src/whatever/..., not a real path in my whole filesystem.

Additional context I don’t really know enough to be able to tell whether this is a Vite bug or us calling Vite in the wrong way. It failing to prebundle certain dependencies makes sense. Some dependencies just won’t work that way. However, it aggressively attempting to prebundle things before they’re even requested by the browser seems questionable. And it then getting into a state where it won’t prebundle anything else is definitely a problem.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:5
  • Comments:12 (6 by maintainers)

github_iconTop GitHub Comments

6reactions
stolinskicommented, Jun 8, 2021

Would it make sense that this is also happening in reverse. ie. my node build is failing from a client only dep. Node is having an issue with a dynamic import of a video player I’m using.

2reactions
Conduitrycommented, Jan 4, 2022

👍 optimizeDeps.exclude worked for me. I’m no longer seeing the issue I mentioned above. I’m guessing that this is because of the fix for the process.env. -> ({}). stuff in SSR that’s happened in Vite in the meantime.

I’m fine with this being closed on our end - we can use the Vite issue for tracking more graceful handling of these errors.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Why Vite
Vite aims to address these issues by leveraging new advancements in the ecosystem: the availability of native ES modules in the browser, and...
Read more >
Of Chickens and Pigs - The Dilemma of Creator Self Promotion
Pigs can't be unbiased so while if they are good at their art can provide insight, they are incapable of being neutral. Chickens...
Read more >
Vite: Rethinking Frontend Tooling by Evan You - GitNation
Vite is a new build tool that intends to provide a leaner, faster, and more friction-less workflow for building modern web apps.
Read more >
Full text of "Flora domestica, or, The portable flower-garden
Our different festivals have each their own peculiar plant, or plants, to be used in their celebration : at Easter the willow as...
Read more >
Is Vite currently the best bundler for Svelte? - codechips
I've heard many good things about Vite and decided to try it out. ... The app might be simple, maybe even naïve, but...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found