Skip to content

Nitro's moduleSideEffects defaults override Rolldown settings, causing aggressive tree-shaking #4085

Closed

Description

@Teages

Environment

Nitro v3 with Vite

Reproduction

https://stackblitz.com/edit/nitro-aggressive-treeshake?file=server%2Froutes%2Findex.ts

  1. run npm run dev, get {"items":["a","b"]}
  2. run npm run build, then npm run preview, get {"items":[]}

Describe the bug

Nitro have injected a custom moduleSideEffects config, replace the default config true, makes all module are aggressive tree-shakeable (including workspace code and external packages)

Reference: InputOptions.treeshake#modulesideeffects

Additional context

It is a common usage of pothos, nitro config will tree-shaking the side-effect of the plugin and break the feature

I think we can remove the moduleSideEffects override for safe production builds by default.

Activity

  1. changed the title [-]`moduleSideEffects` defaults override Rolldown settings, causing aggressive tree-shaking[/-] [+]Nitro's `moduleSideEffects` defaults override Rolldown settings, causing aggressive tree-shaking[/+] on Mar 9, 2026
  2. idirdev commented on Mar 11, 2026

    @idirdev

    This is a real problem. Nitro's custom moduleSideEffects config overrides Rolldown's default (which is true, meaning "treat all modules as having side effects"). With the override, Rolldown aggressively tree-shakes modules that register themselves through side effects.

    This is especially bad with plugin-pattern libraries like Pothos where you import a plugin purely for its side effect of registering it with the builder:

    import '@pothos/plugin-prisma';
    // this module's side effect registers the plugin
    // tree-shaking removes it because theres no explicit usage

    Dev mode works (no tree-shaking), production build removes the import and breaks the feature.

    Workaround: mark specific imports as side-effectful in your Nitro config:

    export default defineNitroConfig({
      rollupConfig: {
        treeshake: {
          moduleSideEffects: (id) => {
            if (id.includes('@pothos/')) return true;
            return false;
          },
        },
      },
    });

    The real fix should be on Nitro's side though. Overriding moduleSideEffects to false is too aggressive as a default. Either remove the override (let Rolldown use its default true) or only apply it to known-safe modules.

  3. added a commit that references this issue on Mar 29, 2026
    ebb9329
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions