Tauri + SvelteKit + Vite + CodeMirror 6: Works in Dev, Breaks in Production Build

Hey guys, I’m building an app in Tauri, and using SvelteKit on the front-end (Svelte 5).

The Stack

  • Framework: Tauri 2.0
  • Frontend: SvelteKit (adapter-static, ssr = false, prerender = true)
  • Bundler: Vite
  • Editor: CodeMirror 6
  • Package Manager: pnpm

The Problem

My application works perfectly in development mode (pnpm tauri dev). The CodeMirror editor renders correctly, and all plugins (like autocomplete) function as expected.

However, when I create a production build (pnpm tauri build), the editor breaks in two ways:

  1. Styling Issue: The core layout is broken. The gutter and line numbers are stacked vertically at the top of the editor, and other default CM styles are not present.
  2. Functionality Issue: Plugins like autocomplete do not work at all.

This clearly points to an issue with Vite/Rollup’s production bundling and tree-shaking process.

What I’ve Tried

I have spent many hours trying to resolve this and have gone through every conceivable configuration and implementation strategy, including:

  • Vite Configurations:
    • optimizeDeps.include and optimizeDeps.exclude with all @codemirror packages.
    • ssr.noExternal to force bundling of the packages.
    • build.rollupOptions.treeshake.moduleSideEffects to explicitly tell Rollup not to tree-shake CodeMirror’s side effects.
  • Implementation Changes:
    • Started with svelte-codemirror-editor and then removed it to use the native CodeMirror 6 API directly. The problem persisted.
    • Tried dynamically importing the autocomplete plugin (await import(...)) to prevent it from being tree-shaken. The build produced a warning that the module was also statically imported by other CodeMirror packages, neutralizing the fix.
  • Dependency Management:
    • Downgraded and pinned all @codemirror packages to older, known-stable versions from late 2023/early 2024. The issue remained.

My Conclusion

The issue seems to be that Vite/Rollup’s tree-shaking is incorrectly removing the “side effects” from the @codemirror packages - both the dynamically injected CSS for layout and the JavaScript logic for plugins. None of the standard Vite configurations to control this behavior have worked.

My final attempt at a workaround involved dynamically importing the plugins, but this also failed.

I’m at a completely loss. Any help would be greatly appreciated :folded_hands: Thanks :slight_smile:

I haven’t heard of an issue like this before. There’s a lot going on in build pipelines like this—the problem could be in any of the tools involved. If you’re able to strip this down as much as possible (ideally to just a rollup build, if that can still show the issue), and set up a reproduction, I could take a look and try to debug it.

1 Like

For what it’s worth my app is Svelte 5 + CodeMirror 6 + vite (+ tailwindcss) with bun as package manager and it works just fine in production build.

You can look at my setup GitHub - kjk/edna: Note taking for developers and power users

But it’s basically what you get from vite Svelte template with tailwindcss. I’ve added one advanced thing: manual chunking of production build.

I don’t use optimizeDeps or build.rollupOptions.treeshake.moduleSideEffects. You seem to think they are necessary but if they are not necessary for me, I don’t see why they should be necessary for you.

I don’t do any import tricks. I don’t get why you’re worried about tree-shaking. I import a bunch of codemirror packages and never had a problem of used code being removed. Logically, if your code calls function foo and it gets removed during build, then you’ll get a runtime exception when trying to call it.

Here’s a debugging tip. Add to vite.config.js:

function manualChunks(id) {
  console.log(id);
}

// ...
    rollupOptions: {
      output: {
        manualChunks: manualChunks,
      },
    },

This will print every file that vite build is processing. Maybe that will illuminate something. The layout issue implies that some CSS file is not bundled.

1 Like

Thank you!

This was very helpful, it showed that everything was being bundled properly!

The issue lay with Tauri’s permissions for allowing inline CSS that CodeMirror uses. The fact that autocompletion wasn’t working tricked me into thinking it was a deeper problem than CSS, but of course the autocompletion overlay is triggered by CSS!

The solution was to add this line to the csp field in the Tauri conf:

style-src 'self' 'unsafe-inline'

Everything is working properly now. Thank you :slight_smile: