nuxt: 404 errors don't work on nuxt generate
Environment
- Operating System: Darwin
- Node Version: v16.20.0
- Nuxt Version: 3.6.1
- Nitro Version: 2.5.2
- Package Manager: npm@8.19.4
- Builder: vite
- User Config: -
- Runtime Modules: -
- Build Modules: -
Reproduction
https://staging--coolplanet.netlify.app/404
Describe the bug
We are using Nuxt generate on Netlify to generate pre-rendered routes. however, when doing so, our 404 error page doesn’t render. I can confirm locally in dev mode, the 404 mode works perfectly.
I am using
throw createError({ statusCode: 404 }); to trigger 404s when our fetch calls dont work.
this set up works fine, without pre-rendering enabled.
Additional context
This is my nuxt.config
import { resolve } from "path";
import sanityClient from "@sanity/client";
import dynamicRoutes from "./helpers/dynamicRoutes";
const client = sanityClient({
projectId: process.env.SANITY_PROJECT_ID,
apiVersion: process.env.SANITY_API_VERSION,
useCdn: process.env.SANITY_CDN,
dataset: process.env.SANITY_DATASET,
});
export const getRedirects = async () => {
let redirectsObject = {};
const redirectQuery = `*[_type == "redirect"]{
'from':fromPath,
'redirect':{'to':toPath, 'statusCode':statusCode}
}`;
const data = await client.fetch(redirectQuery);
if (data && data.length) {
data.forEach((item) => {
redirectsObject[item.from] = {
redirect: item.redirect,
};
});
console.info("Redirects are generated");
} else {
console.info("No redirects sourced");
}
return redirectsObject;
};
export default defineNuxtConfig({
app: {
head: {
title: "Cool Planet",
htmlAttrs: {
lang: "en-GB",
},
meta: [
{ name: "viewport", content: "width=device-width, initial-scale=1" },
{ charset: "utf-8" },
],
link: [
{
rel: "apple-touch-icon",
sizes: "180x180",
href: "/favicon/apple-touch-icon.png",
},
{
rel: "icon",
type: "image/png",
sizes: "32x32",
href: "/favicon/favicon-32x32.png",
},
{
rel: "icon",
type: "image/png",
sizes: "16x16",
href: "/favicon/favicon-16x16.png",
},
{ rel: "manifest", href: "/favicon/site.webmanifest" },
],
script:[
{id:"youtube-iframe-js-api-script",
src:"https://www.youtube.com/iframe_api"}
]
},
},
modules: [
"@nuxtjs/sanity",
"nuxt-jsonld",
"@pinia/nuxt",
"@nuxt/image-edge",
"@nuxtjs/robots",
"nuxt-simple-sitemap",
'nuxt-schema-org'
],
routeRules: getRedirects(),
hooks: {
"pages:extend"(pages) {
pages.push(
{
name: "site.blogIndex",
path: "/blog",
file: resolve("/pages/blog/page/[page].vue"),
},
{
name: "site.caseStudiesIndex",
path: "/case-studies",
file: resolve("/pages/case-studies/page/[page].vue"),
},
{
name: "site.articlesIndex",
path: "/blog/articles",
file: resolve("/pages/blog/articles/page/[page].vue"),
},
{
name: "site.featuresIndex",
path: "/blog/featured",
file: resolve("/pages/blog/featured/page/[page].vue"),
},
{
name: "site.reportsIndex",
path: "/blog/reports",
file: resolve("/pages/blog/reports/page/[page].vue"),
},
{
name: "site.masterclassesIndex",
path: "/blog/masterclasses",
file: resolve("/pages/blog/masterclasses/page/[page].vue"),
}
);
},
},
robots: () => {
if (process.env.ENVIRONMENT && process.env.ENVIRONMENT === "production") {
// production environment - allow robots
return {
sitemap: process.env.BASE_URL + "/sitemap.xml",
UserAgent: "*",
Disallow: ["/admin", "/.env", "/users"],
};
} else {
// every other environment - block robots
return {
sitemap: process.env.BASE_URL + "/sitemap.xml",
UserAgent: "*",
Disallow: "/",
};
}
},
sitemap:{
exclude:[
'/styles',
'/kitchen-sink'
]
},
sanity: {
projectId: process.env.SANITY_PROJECT_ID,
apiVersion: process.env.SANITY_API_VERSION,
useCdn: process.env.SANITY_CDN,
dataset: process.env.SANITY_DATASET,
},
runtimeConfig: {
public:{
siteName:'Cool Planet',
siteUrl:process.env.BASE_URL,
baseUrl:process.env.BASE_URL,
gtmId:process.env.GTM_ID
},
},
target: "static",
image: {
// Options
sanity: {
projectId: "say5yn59",
dataset: "production",
},
screens: {
xxs: 320,
xs: 359,
sm: 640,
md: 768,
lg: 1024,
xl: 1280,
xxl: 1536,
xxxl: 1920,
quadHd: 2400,
"4k": 3700,
},
},
css: ["@/assets/scss/main.scss"],
vite: {
css: {
preprocessorOptions: {
scss: {
additionalData: '@use "@/assets/scss/tools.scss" as *;',
},
},
},
},
alias: {
"@app": "/@app",
},
nitro: { // was required to add this for the nuxt/simple-sitemap module
prerender: {
crawlLinks: true,
routes: [
'/',
'/404.html' // was told online to try this, but didn't work
]
}
}
});
Logs
No response
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 55 (8 by maintainers)
Let’s track in https://github.com/nuxt/nuxt/issues/18718.
@annymosse If you want a Nuxt site with zero JS, it’s as simple as:
Hi @annymosse ,
It does solve the static pages if you can prerender them. In case of storyblok, I can get all stories and then prerender then in the nitro hook
Ignore target static - that was a mistake. Did you try the nitro pretender settings?
Could it be the fact you are using
pnpm? I have not switched to this yet, but can confirm it works with classicnpm.Otherwise it might be to do with how your throwing your 404 errors – code here, as it looks like your 404s are being thrown before the API query is complete. Did you try using nuxt’s standard lazyAsyncData instead, in combination with checking for the pending listener as suggested here?
Hi, I had a similar issue with Sanity’s wrapper for Async Data, which looks similar to StoryBloks. So I ditched that and just used Nuxt’s default useAsyncData, in combination with Sanity fetch.
@stijns96 I use Storyblok and ran into some issues too with that, this is what I got it to work in my […slug].vue
@toddpadwick can confirm the issue was using pnpm generate rather than pnpm build.
Resolved my issues right away!
Hi all. So heres the detailed break down of how I fixed this:
Do not use
nuxt generate. Instead usenuxt build. Initially I thought Nuxt Generate was required for static generation but its not. I have Nuxt set up to runnpm run buildbut to ensure the site is pre-crawled and generated on build, in my nuxt.config I have the following added:Ensure 400 and 500 errors are fatal Now, I went back and forth with Daniel on this and initial it seemed I could not use lazyAsyncData as the errors were being thrown before the fetch call was complete. But I managed to get it working by doing the following:
I can confirm this successfully pre-crawls and generates the entire site and 404s work just fine on netlify. Hope this helps 😃
oh sorry, i’ll email you. found you email on the profile 😃
@toddpadwick Happy to help but really we’d need more info - sharing the code would be perfect. Feel free to DM if there’s info you can’t share in this issue.