nuxt-modules / i18n

I18n module for Nuxt
https://i18n.nuxtjs.org
MIT License
1.71k stars 478 forks source link

Nuxt generate creates missing CSS when i18n.config.ts is present #2189

Closed mzenz closed 1 year ago

mzenz commented 1 year ago

Environment

Reproduction

https://github.com/mzenz/nuxt-i18n-ssg-bug

Describe the bug

When configuring i18n via i18n.config.ts prerendering via nuxt generate, CSS styles are not present in the prerendered output.

This is fixed by removing i18n.config.ts altogether which means some i18n options can't be configured.

Steps to reproduce

  1. git clone https://github.com/mzenz/nuxt-i18n-ssg-bug.git
  2. yarn install
  3. yarn generate
  4. run yarn serve to start a local static web server
  5. Navigate to http://localhost:3000

Actual results

Expected results

Additional context

Broken index.html (no <style> tag):

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>Welcome</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="preload" as="fetch" crossorigin="anonymous" href="/_payload.json">
  <link rel="modulepreload" as="script" crossorigin href="/_nuxt/i18n.config.72a0045f.js">
  <link rel="modulepreload" as="script" crossorigin href="/_nuxt/entry.1786a013.js">
  <link rel="modulepreload" as="script" crossorigin href="/_nuxt/index.8471fa67.js">
  <link rel="prefetch" as="script" crossorigin href="/_nuxt/i18n.options.f2c7cfbd.js">
  <link rel="prefetch" as="script" crossorigin href="/_nuxt/error-404.ed81c13f.js">
  <link rel="prefetch" as="script" crossorigin href="/_nuxt/error-500.45f394fd.js">
</head>

<body>
  <div id="__nuxt"><!--[-->
    <h1>Welcome</h1>
    <h2>en 🇺🇸</h2><button>Next language</button><br><label>Language</label><select name="locales"><!--[-->
      <option value="en">en</option>
      <option value="es">es</option><!--]-->
    </select><br><span>This string doesn&#39;t change</span><!--]-->
  </div>
  <script type="application/json" id="__NUXT_DATA__" data-ssr="true"
    data-src="/_payload.json">[{"state":1,"_errors":3,"serverRendered":5,"path":6,"prerenderedAt":7},["Reactive",2],{},["Reactive",4],{},true,"/",1688220237087]</script>
  <script>window.__NUXT__ = {}; window.__NUXT__.config = { public: { i18n: { experimental: { jsTsFormatResource: false }, baseUrl: "" } }, app: { baseURL: "/", buildAssetsDir: "/_nuxt/", cdnURL: "" } }</script>
  <script type="module" src="/_nuxt/i18n.config.72a0045f.js" crossorigin></script>
  <script type="module" src="/_nuxt/entry.1786a013.js" crossorigin></script>
</body>

</html>

Sane index.html (i.e. <style> tag present):

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>Welcome</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="preload" as="fetch" crossorigin="anonymous" href="/_payload.json">
  <link rel="modulepreload" as="script" crossorigin href="/_nuxt/entry.3bd2eaf4.js">
  <link rel="modulepreload" as="script" crossorigin href="/_nuxt/index.6b5dc2c4.js">
  <link rel="prefetch" as="script" crossorigin href="/_nuxt/error-404.8b1d248d.js">
  <link rel="prefetch" as="script" crossorigin href="/_nuxt/error-500.bd8ad439.js">
  <style>
    body {
      background-color: cyan
    }
  </style>
</head>

<body>
  <div id="__nuxt"><!--[-->
    <h1>Welcome</h1>
    <h2>en 🇺🇸</h2><button>Next language</button><br><label>Language</label><select name="locales"><!--[-->
      <option value="en">en</option>
      <option value="es">es</option><!--]-->
    </select><br><span>This string doesn&#39;t change</span><!--]-->
  </div>
  <script type="application/json" id="__NUXT_DATA__" data-ssr="true"
    data-src="/_payload.json">[{"state":1,"_errors":3,"serverRendered":5,"path":6,"prerenderedAt":7},["Reactive",2],{},["Reactive",4],{},true,"/",1688220541253]</script>
  <script>window.__NUXT__ = {}; window.__NUXT__.config = { public: { i18n: { experimental: { jsTsFormatResource: false }, baseUrl: "" } }, app: { baseURL: "/", buildAssetsDir: "/_nuxt/", cdnURL: "" } }</script>
  <script type="module" src="/_nuxt/entry.3bd2eaf4.js" crossorigin></script>
</body>

</html>

Logs

yarn run v1.22.19
$ nuxt generate
Nuxi 3.6.1
Nuxt 3.6.1 with Nitro 2.5.2

 WARN  Using experimental payload extraction for full-static output. You can opt-out by setting experimental.payloadExtraction to false.

[@nuxtjs/i18n]  WARN  i18n:extend-messages is deprecated. That hook will be removed feature at the time of the v8 official release.
If you're using it, please use i18n:registerModule instead.

ℹ Building client...
ℹ vite v4.3.9 building for production...
ℹ transforming...
ℹ ✓ 138 modules transformed.
ℹ rendering chunks...
ℹ computing gzip size...
ℹ .nuxt/dist/client/i18n-meta.json                    0.09 kB │ gzip:  0.09 kB
ℹ .nuxt/dist/client/manifest.json                     2.54 kB │ gzip:  0.50 kB
ℹ .nuxt/dist/client/_nuxt/error-500.aa16ed4d.css      1.95 kB │ gzip:  0.74 kB
ℹ .nuxt/dist/client/_nuxt/error-404.23f2309d.css      3.63 kB │ gzip:  1.12 kB
ℹ .nuxt/dist/client/_nuxt/i18n.config.72a0045f.js     0.09 kB │ gzip:  0.10 kB
ℹ .nuxt/dist/client/_nuxt/i18n.options.f2c7cfbd.js    0.41 kB │ gzip:  0.28 kB
ℹ .nuxt/dist/client/_nuxt/index.8471fa67.js           0.76 kB │ gzip:  0.47 kB
ℹ .nuxt/dist/client/_nuxt/error-500.45f394fd.js       1.88 kB │ gzip:  0.99 kB
ℹ .nuxt/dist/client/_nuxt/error-404.ed81c13f.js       6.53 kB │ gzip:  2.91 kB
ℹ .nuxt/dist/client/_nuxt/entry.1786a013.js         196.45 kB │ gzip: 71.73 kB
ℹ ✓ built in 3.85s
✔ Client built in 3860ms
ℹ Building server...
ℹ vite v4.3.9 building SSR bundle for production...
ℹ transforming...
ℹ ✓ 87 modules transformed.
ℹ rendering chunks...
(nuxtjs:i18n-resource-dynamic plugin) Sourcemap is likely to be incorrect: a plugin (nuxtjs:i18n-resource-dynamic) was used to transform files, but didn't generate a sourcemap for the transformation. Consult the plugin documentation for help
ℹ .nuxt/dist/server/_nuxt/entry-styles.1608fffe.mjs             0.08 kB
ℹ .nuxt/dist/server/i18n-meta.json                              0.09 kB
ℹ .nuxt/dist/server/_nuxt/error-404-styles.cf00f4cc.mjs         0.15 kB
ℹ .nuxt/dist/server/_nuxt/error-500-styles.a001b7ed.mjs         0.15 kB
ℹ .nuxt/dist/server/styles.mjs                                  0.46 kB
ℹ .nuxt/dist/server/_nuxt/entry-styles-1.mjs-709fbf95.js        0.13 kB │ map:   0.11 kB
ℹ .nuxt/dist/server/_nuxt/i18n.config-6e753f3f.js               0.19 kB │ map:   0.11 kB
ℹ .nuxt/dist/server/_nuxt/index-e12b288f.js                     0.22 kB │ map:   5.28 kB
ℹ .nuxt/dist/server/_nuxt/island-renderer-f6748c54.js           1.27 kB │ map:   1.41 kB
ℹ .nuxt/dist/server/_nuxt/i18n.options-d8f5dc0d.js              1.48 kB │ map:   0.16 kB
ℹ .nuxt/dist/server/_nuxt/index-c94003f5.js                     1.83 kB │ map:   1.18 kB
ℹ .nuxt/dist/server/_nuxt/error-500-styles-1.mjs-0a86f27a.js    2.17 kB │ map:   0.12 kB
ℹ .nuxt/dist/server/_nuxt/error-500-a3588b31.js                 3.27 kB │ map:   3.79 kB
ℹ .nuxt/dist/server/_nuxt/error-404-styles-1.mjs-6ef6e240.js    3.86 kB │ map:   0.12 kB
ℹ .nuxt/dist/server/_nuxt/error-404-348568b4.js                 9.92 kB │ map:  18.92 kB
ℹ .nuxt/dist/server/server.mjs                                147.77 kB │ map: 360.27 kB
ℹ ✓ built in 1.62s
✔ Server built in 1633ms
[nitro] ✔ Generated public .output/public
[nitro] ℹ Initializing prerenderer
[nitro] ℹ Prerendering 4 initial routes with crawler
[nitro]   ├─ / (96ms)
[nitro]   ├─ /200.html (4ms)
[nitro]   ├─ /404.html (2ms)
[nitro]   ├─ /__i18n__/prerender/8dca6fa6.js (10ms)
[nitro]   ├─ /_payload.json (1ms)
[nitro] ✔ You can preview this build using npx serve .output/public
✔ You can now deploy .output/public to any static hosting!
Done in 15.80s.
kazupon commented 1 year ago

duplicate #2177

This issue is fixed with https://github.com/nuxt/nuxt/pull/21864 You can try to confirm nuxt edge channel

Thanks!

codetheorist commented 11 months ago

This issue is still a thing when building using Docker.

I'm using the following package.json:

{
  ...,
  "dependencies": {
    "@babel/runtime-corejs3": "^7.22.5",
    "@fortawesome/fontawesome-free": "^5.15.4",
    "@fortawesome/free-brands-svg-icons": "^5.15.4",
    "@fortawesome/free-regular-svg-icons": "^5.15.4",
    "@fortawesome/free-solid-svg-icons": "^5.15.4",
    "@fortawesome/vue-fontawesome": "^3.0.3",
    "@googlemaps/markerclusterer": "^2.3.2",
    "@pinia-orm/nuxt": "^1.7.0",
    "@sentry/browser": "^7.73.0",
    "@sentry/cli": "^2.19.1",
    "@sentry/tracing": "^7.57.0",
    "@sentry/vue": "^7.57.0",
    "@vuelidate/core": "^2.0.3",
    "@vuelidate/validators": "^2.0.3",
    "admin-lte": "^3.2.0",
    "animate.css": "^4.1.1",
    "axios": "^0.27.2",
    "babel-plugin-module-resolver": "^5.0.0",
    "date-fns": "^2.30.0",
    "firebase": "^10.0.0",
    "geojson": "^0.5.0",
    "http-status-codes": "^2.3.0",
    "is-https": "^4.0.0",
    "leaflet": "1.9.4",
    "lodash": "^4.17.21",
    "maska": "^2.1.10",
    "mime-types": "^2.1.35",
    "nuxt-leaflet": "0.0.27",
    "ofetch": "^1.3.3",
    "papaparse": "^5.4.1",
    "pinia": "^2.1.6",
    "pinia-orm": "^1.7.2",
    "pluralize": "^8.0.0",
    "portal-vue": "^3.0.0",
    "requrl": "^3.0.2",
    "uuid": "^9.0.0"
  },
  "devDependencies": {
    "@babel/core": "^7.22.5",
    "@babel/eslint-parser": "^7.22.5",
    "@babel/preset-env": "^7.22.20",
    "@bootstrap-vue-next/nuxt": "^0.13.3",
    "@commitlint/cli": "^17.7.2",
    "@commitlint/config-conventional": "^17.6.5",
    "@dargmuesli/nuxt-cookie-control": "^6.4.3",
    "@intlify/unplugin-vue-i18n": "^0.8.2",
    "@nuxt/content": "^2.8.2",
    "@nuxt/devtools": "^0.8.4",
    "@nuxt/devtools-ui-kit": "^0.8.4",
    "@nuxt/image": "^1.0.0-rc.1",
    "@nuxt/test-utils": "^0.2.2",
    "@nuxt/types": "^2.17.1",
    "@nuxt/webpack-builder": "^3.7.4",
    "@nuxtjs/color-mode": "^3.3.0",
    "@nuxtjs/device": "^3.1.1",
    "@nuxtjs/eslint-config": "^12.0.0",
    "@nuxtjs/eslint-module": "^4.1.0",
    "@nuxtjs/fontawesome": "^1.1.2",
    "@nuxtjs/google-adsense": "^2.1.0",
    "@nuxtjs/google-fonts": "^3.0.2",
    "@nuxtjs/html-validator": "^1.5.2",
    "@nuxtjs/i18n": "^8.0.0-rc.4",
    "@nuxtjs/robots": "^3.0.0",
    "@nuxtjs/stylelint-module": "^5.1.0",
    "@pinia/nuxt": "^0.4.11",
    "@sentry/webpack-plugin": "^2.7.1",
    "@sidebase/nuxt-auth": "^0.6.0-beta.5",
    "@sidebase/nuxt-session": "^0.2.7",
    "@types/leaflet": "^1.9.6",
    "@types/node": "^18.16.19",
    "@typescript-eslint/eslint-plugin": "^5.62.0",
    "@typescript-eslint/parser": "^5.62.0",
    "@unhead/schema-org": "^1.7.4",
    "@vueuse/core": "^10.4.1",
    "@vueuse/nuxt": "^10.4.1",
    "bootstrap": "^5.3.2",
    "bootstrap-vue-next": "^0.13.2",
    "cross-env": "^7.0.3",
    "dayjs-nuxt": "^1.1.2",
    "eslint": "^8.45.0",
    "eslint-config-prettier": "^8.5.0",
    "eslint-plugin-import": "^2.26.0",
    "eslint-plugin-jest": "^27.0.4",
    "eslint-plugin-lodash": "^7.4.0",
    "eslint-plugin-node": "^11.1.0",
    "eslint-plugin-nuxt": "^4.0.0",
    "eslint-plugin-prettier": "^4.2.1",
    "eslint-plugin-unicorn": "^47.0.0",
    "eslint-plugin-vue": "^9.5.1",
    "fibers": "^5.0.3",
    "husky": "^8.0.3",
    "jest": "^29.5.0",
    "jest-environment-jsdom": "^29.5.0",
    "jest-scss-transform": "^1.0.3",
    "jest-serializer-vue": "^2.0.2",
    "js-beautify": "^1.14.9",
    "jsdom-global": "^3.0.2",
    "json-loader": "^0.5.7",
    "lint-staged": "^13.2.2",
    "mapbox-gl": "^2.15.0",
    "next-auth": "4.22.3",
    "nuxt": "^3.7.4",
    "nuxt-bugsnag": "^7.0.0",
    "nuxt-gtag": "^1.1.1",
    "nuxt-icon": "^0.5.0",
    "nuxt-lodash": "^2.5.0",
    "nuxt-mapbox": "^1.4.4",
    "nuxt-module-feed": "^1.0.3",
    "nuxt-security": "^0.14.4",
    "nuxt-simple-sitemap": "^3.3.4",
    "nuxt-swiper": "^1.2.2",
    "postcss": ">=8.4.31",
    "prettier": "^3.0.3",
    "require-extension-hooks": "^0.3.3",
    "require-extension-hooks-babel": "^1.0.0",
    "require-extension-hooks-vue": "^3.0.0",
    "sass": "^1.68.0",
    "sass-loader": "^10.3.1",
    "semver": "^7.5.4",
    "stylelint": "^15.10.3",
    "stylelint-config-recommended-vue": "^1.4.0",
    "stylelint-config-standard": "^33.0.0",
    "tsutils": "^3.21.0",
    "typescript": "^5.1.3",
    "vite-plugin-electron": "^0.14.1",
    "vite-plugin-electron-renderer": "^0.14.5",
    "vue-eslint-parser": "^9.3.1",
    "vue-jest": "^3.0.4"
  }
}

Here is my Dockerfile:

# syntax = docker/dockerfile:1
ARG NODE_VERSION=18.18.2

FROM node:${NODE_VERSION} as base

ARG PORT=3000
ENV NODE_ENV=production

WORKDIR /

# Build
FROM base as build

COPY --link package.json package-lock.json .
RUN npm install --production=false

COPY --link . .

RUN npm run build
RUN npm prune

# Run
FROM base as run

ENV PORT=$PORT

COPY --from=build /.output /.output
# Optional, only needed if you rely on unbundled dependencies
COPY --from=build /node_modules /node_modules

CMD [ "node", ".output/server/index.mjs" ]

This issue only occurs when building a Docker image. A regular npm run build && npm run preview works, as does npm run build && node ./.output/server/index.mjs.

codetheorist commented 11 months ago

I'm currently in the process of removing packages until the bug no longer exists.

I will also try a fresh app with only Bootstrap Vue and see if the SCSS still compiles.

codetheorist commented 11 months ago

Also, I'm not entirely sure if my issue is related to cached Docker builds, but I've tried building with different tags & versions, but the end results is always missing CSS.

BobbieGoede commented 11 months ago

@codetheorist Have you tried building your project, then copying the .output and node_modules (as you do in your Dockerfile) into a seperate folder and running node ./.output/server/index.mjs? This at least would exclude any issues caused from copying and missing some assets.

Still, I doubt this issue is caused by @nuxtjs/i18n, but if it is I would be happy to look into it if you could provide a minimal reproduction 😅

codetheorist commented 11 months ago

So, I'm not sure what the issue was.

I ended up starting a fresh project and progressively copying parts from the old project to the new, to see when the CSS stopped working. It didn't stop working.

Weird issue and I've never got to the bottom of what was causing it.