nuxt / nuxt

The Intuitive Vue Framework.
https://nuxt.com
MIT License
54.34k stars 4.97k forks source link

Nuxt fails to preserve a side-effect only import in server build #20707

Closed brawaru closed 3 months ago

brawaru commented 1 year ago

Environment

Nuxi 3.4.3 RootDir: /home/projects/nuxt-starter-hpuww7 Nuxt project info:


Reproduction

  1. Install @vintl/compact-number
  2. Import @vintl/compact-number/locale-data/en without any specifiers (side-effect only import)

https://stackblitz.com/edit/nuxt-starter-hpuww7?file=app.vue

Describe the bug

Nuxt successfully preserves the import in both .nuxt/dist/client (search thousand in .nuxt/dist/client/_nuxt/entry.xxxxxx.js) and .nuxt/dist/server (.nuxt/dist/server/server.mjs has the import line), however the Nitro server build in .output fails to preserve the import, which causes an error in real applications. In @vintl/compact-number case it's a locale data required for the package to function properly.

Additional context

N/D

Logs

N/A
danielroe commented 1 year ago

Would you try something like this?

export default defineNuxtConfig({
  nitro: {
    moduleSideEffects: ['@vintl/compact-number/locale-data/en']
  }
})
brawaru commented 1 year ago

Oh, thank you so much, Daniel! Adding moduleSideEffects: ['@vintl/compact-number/locale-data'] does seem to mitigate this and import appears in .output/server/chunks/app/server.mjs.

Though I'm still not sure why Nitro would want to override the default @rollup/plugin-node-resolve behaviour for deciding side effect only imports, which, as I understand, is based on sideEffects in package.json and more or less universally accepted across different bundlers ^1 ^3 (changing it made the import appear in .nuxt/dist outputs, but not nitro server build).

danielroe commented 1 year ago

cc: @pi0

issue-up[bot] commented 1 year ago

Upstream issue created:

matafokka commented 1 year ago

Hello everyone! I have the same issue but with local modules, and I found a temporary solution.

TLDR: Moving pages to the /components/ directory fixed the issue.

Basically, I have a module with the locales object like this:

export interface LocaleKeys { [key: string]: string }

export interface Locale {
  [scope: string]: LocaleKeys;
}

const locales = reactive<{
  [code: string]: {
    name: string;
    scopes: Locale;
  };
}>({});

To split locales into small pieces (scopes), in each part of the application (components, pages, etc) I modify this object with the helper addKeys() function like so:

addKeys("EN_US", "localeKey", {
  key1: "value1",
  key2: "value2",
});

And I have an index.ts file that imports all locales in a scope.

When I import index.ts in a .vue file inside /components/ directory, it works fine.

When I import index.ts in a .vue file inside /pages/ directory, it prints "hydration mismatch" in a browser when I build my app. I found that Nitro completely ignores this import on server side.

I haven't checked if components or modules in other directories have the same issue.

As a quick and dirty fix, I just moved all my pages to the /components/ directory.

Note: I use /app/router.options.ts file to configure routes. To use this fix, you need to either use this file or change pages directory at nuxt.config.ts file - whatever suits you the most.

danielroe commented 3 months ago

If you're still experiencing this, would you see if you can reproduce this in pure Nitro (reproduction sandbox), and if so, raise there? 🙏

If it only recurs with Nuxt, let me know and I'll reopen it here.