i18n icon indicating copy to clipboard operation
i18n copied to clipboard

Building app using `strategy: 'prefix'` throws pre-render `(Error: [301])`

Open Dananz opened this issue 2 years ago • 13 comments

Environment

  • Operating System: Darwin
  • Node Version: v16.16.0
  • Nuxt Version: 3.6.5
  • Nitro Version: 2.5.2
  • Package Manager: [email protected]
  • Builder: vite
  • User Config: -
  • Runtime Modules: -
  • Build Modules: -

Reproduction

https://stackblitz.com/edit/nuxt-starter-jkohmm?file=nuxt.config.ts

Describe the bug

When trying to use strategy: 'prefix', Im getting (Error: [301])

image

Additional context

No response

Logs

✔ Server built in 920ms                                                                                                                                                           12:55:12 PM
✔ Generated public .output/public                                                                                                                                           nitro 12:55:12 PM
ℹ Initializing prerenderer                                                                                                                                                  nitro 12:55:12 PM
ℹ Prerendering 2 routes                                                                                                                                                     nitro 12:55:13 PM
  ├─ /test (64ms) (Error: [301] )                                                                                                                                            nitro 12:55:13 PM
  ├─ / (65ms) (Error: [301] )                                                                                                                                                nitro 12:55:13 PM
                                                                                                                                                                             nitro 12:55:13 PM
Errors prerendering:
  ├─ /test (301)                                                                                                                                                             nitro 12:55:13 PM
  ├─ / (301)                                                                                                                                                                 nitro 12:55:13 PM
                                                                                                                                                                             nitro 12:55:13 PM

 ERROR  Exiting due to prerender errors.                                                                                                                                           12:55:13 PM

  at Module.prerender (node_modules/nitropack/dist/shared/nitro.1db3349c.mjs:204:11)
  at async eval (node_modules/nuxt/dist/index.mjs:2658:7)
  at async build (node_modules/nuxt/dist/index.mjs:3811:5)
  at async Object.invoke (node_modules/nuxi/dist/chunks/build.mjs:74:5)
  at async _main (node_modules/nuxi/dist/cli.mjs:64:20)

Dananz avatar Jul 23 '23 09:07 Dananz

Thank you for your reporting!

This issue is not with the nuxt i18n module, because you are prerendering the build with the routeRules option in order to make it work in SSR mode.

The prefix strategy redirects to a URL with the target locale when accessing root /. (Error: [301]) occurs because you have set a prerender in your routeRules options, which is redirected by the prefix strategy described above.

I saw your nuxt.config.ts and the nuxi build is a build to run on a server in SSR mode. I don`t know why you are prerendering (I would like to know the reason why you will prerender), but there is a way to work around this error below.

  1. stop prerender
  2. set ssr: false on nuxt.config
  3. set nitro.prerender.failOnError: false on nuxt.config: (ref: https://github.com/nuxt/nuxt/issues/22159#issuecomment-1639851186)

kazupon avatar Jul 24 '23 09:07 kazupon

@kazupon My app is heavily relaying on routeRules, some pages needs to be prerendered (landing page & some other commercial pages) while others are meant to be fully client only pages (dashboard, kyc & more)

If I'll remove ssr and prerender the entire app will act as an spa.

whats the best / right way to use strategy prefix with routeRules?

Dananz avatar Jul 25 '23 17:07 Dananz

Thank you for your use-cases.

Your reproduction of the routing strategy uses prefix. And your locale code is en and he. So you can prerender your application and build it with SSR by setting the routeRules option as follows:

  routeRules: {
    '/en': { prerender: true },
    '/he': { prerender: true },
    '/en/test': { prerender: true },
    '/he/test': { prerender: true },
  },

kazupon avatar Jul 26 '23 02:07 kazupon

Thank you for your use-cases.

Your reproduction of the routing strategy uses prefix. And your locale code is en and he. So you can prerender your application and build it with SSR by setting the routeRules option as follows:

  routeRules: {
    '/en': { prerender: true },
    '/he': { prerender: true },
    '/en/test': { prerender: true },
    '/he/test': { prerender: true },
  },

Thank you for adding some examples on how to fix it, your solution could help But I keep getting 301 for the main index page (/). it seems that even if I remove the entire routeRules object it still prerendering the index page. This one is a bit tricky and I couldn't reproduce it on Stackblitz..

image

Dananz avatar Jul 26 '23 07:07 Dananz

You can specifically set your root to not prerender. This solved it for me:

routeRules: {
      "/": { prerender: false },
      "/de": { prerender: true },
      "/en": { prerender: true },
    },

martflu avatar Jul 26 '23 09:07 martflu

And its fine to not have a root index.html file ?

Dananz avatar Jul 26 '23 09:07 Dananz

@kazupon @martflu any suggestions on how to handle the root index.html file while using strategy prefix?

I cant publish my app without having a root index.html.

Dananz avatar Aug 06 '23 09:08 Dananz

@kazupon and btw, any reason why other strategies totally ignores routeRules? my build is failing for pages that shouldn't be pre-rendered, for example, the build will fail for all the following rules: "/kyc/**": { ssr: false },

the only strategy that respects the routeRules object is prefix. but Im actually looking for a prefix_except_default strategy.

Any suggestions?

Dananz avatar Aug 06 '23 09:08 Dananz

@Dananz I am using prefix with an index page. With this setting, root will always forward to one of the prefixes. This forward was the reason for the Error during prerender. Specifically setting the unprefixed root to be excluded during prerender solved the problem for me. I also use crawlLinks: true for prerendering all other routes of the page.

martflu avatar Aug 07 '23 14:08 martflu

@Dananz I am using prefix with an index page. With this setting, the root will always forward to one of the prefixes. This forward was the reason for the Error during prerender. Specifically setting the unprefixed root to be excluded during prerender solved the problem for me. I also use crawlLinks: true for prerendering all other routes of the page.

Can some expert verify this gentleman's statement? seems correct to me.

NageshSingh-VidyaMantra avatar Aug 17 '23 10:08 NageshSingh-VidyaMantra

When I set { prerender: false } in the "/" route, it works. However, it doesn't work for "/nl, "/nl/", and any other routes generated by nuxt-i18n :/ image image

szulcus avatar Oct 09 '23 13:10 szulcus

disclaimer

i am not planning on running this static so nuxt generate was a mistake in my case for this particular project.

i18n: {
    lazy: true,
    langDir: "locales/",
    defaultLocale: "en",
    strategy: "prefix",
    detectBrowserLanguage: {
      useCookie: true,
      cookieKey: "i18n_redirected",
      fallbackLocale: "en",
      redirectOn: "root",
    },
    customRoutes: "config",
    pages: {
      about: {
        de: "/ueber-mich",
        en: "/about",
      },
    },
    locales: [
      {
        name: "Deutsch",
        code: "de",
        iso: "de-DE",
        file: "de",
        icon: "i-circle-flags-de",
      },
      {
        name: "English",
        code: "en",
        iso: "en-US",
        file: "en",
        icon: "i-circle-flags-en",
      },
    ],
  },
│   .gitignore
│   app.config.ts
│   app.vue
│   nuxt.config.ts
│   package-lock.json
│   package.json
│   README.md
│   tailwind.config.js
│   tsconfig.json
├───locales
│   ├───de
│   │       index.ts
│   │
│   └───en
│           index.ts
└───pages
│       about.vue
│       index.vue

running generate results in an error Error: [404] Page not found: /

Prerendering 7 initial routes with crawler   
  ├─ /200.html (37ms)                           
  ├─ /404.html (38ms)                           
  ├─ / (108ms)                                                                         
  │ └── Error: [404] Page not found: /
  ├─ /en (103ms)                                                                  
  ├─ /en/about (83ms)                                                     
  ├─ /de (104ms)                                                         
  ├─ /de/ueber-mich (104ms)                                     
  ├─ /en/about/_payload.json (0ms)                           
  ├─ /en/_payload.json (1ms)                                          
  ├─ /de/_payload.json (3ms)                                   
  ├─ /de/ueber-mich/_payload.json (1ms) 
                                                                                 
Errors prerendering:
  ├─ / (108ms)                                                   
  │ └── Error: [404] Page not found: /
                                                                              

 ERROR  Exiting due to prerender errors. 

Sazzels avatar Dec 28 '23 03:12 Sazzels

I need to use generate and have the same problem. In my case i switched to prefix because of SEO Issues.

ml1nk avatar Jan 31 '24 12:01 ml1nk

@Sazzels I'm facing the same issue for the default route. / seems to throw a 404 when running generate.

In my case I "fixed" it by adding a rootRedirect to the i18n options:

i18n: {
  rootRedirect: 'en' // use default locale 
}

But this also throws a warning when running dev: [Vue Router warn]: No match found for location with path "/en/en". The redirect seems to be correct though.

bnachtweh avatar Apr 03 '24 09:04 bnachtweh

This issue should be (at least partially) fixed by #2894 which is included in the edge release, I have updated the original reproduction to demonstrate here.

Please let me know if any of you still run into this issue when using the edge release, install with npm i -D @nuxtjs/i18n@npm:@nuxtjs/i18n-edge, you may need to remove lockfiles before installing.

BobbieGoede avatar Apr 03 '24 09:04 BobbieGoede

@BobbieGoede the nuxt generate command seems to work as expected now, except the root redirect is always to /en when I configure my i18n as follows:

i18n: {
    locales: [
        {
            code: 'nl',
            iso: 'nl-NL',
        },
        {
            code: 'en',
            iso: 'en-US',
        },
    ],
    defaultLocale: 'nl',
    strategy: 'prefix',
    vueI18n: './i18n.config.ts',
},
import en from '@/i18n/messages/en';
import nl from '@/i18n/messages/nl';

export default defineI18nConfig(() => ({
	legacy: false,
	locale: 'nl',
	locales: [
		{
			code: 'en',
			iso: 'en-US',
		},
		{
			code: 'nl',
			iso: 'nl-NL',
		},
	],
	messages: {
		en,
		nl,
	},
}));

I would expect the redirect from / to go to the configured defaultLocale if set.

bnachtweh avatar Apr 04 '24 17:04 bnachtweh

@bnachtweh Can you provide a minimal reproduction project?

BobbieGoede avatar Apr 04 '24 17:04 BobbieGoede

@bnachtweh Can you provide a minimal reproduction project?

Never mind, it seems that the cookie was set to en, so that would make sense. Thanks anyway!

bnachtweh avatar Apr 05 '24 10:04 bnachtweh

Since the original issue should be resolved I'll close this issue. If anyone is running into issues please open a new issue with a minimal reproduction!

BobbieGoede avatar Apr 05 '24 17:04 BobbieGoede