Next.js动态路由生产环境失效,部署AWS EC2后出现404错误
Next.js生产环境动态路由404问题解决
问题场景
基于Next.js开发的Web应用,后端使用Node.js实现。开发模式下动态路由功能正常,部署到AWS EC2生产环境后,访问如dashboard/seller/4这类动态路由页面返回404错误,应用其余功能均正常,开发模式下API调用无问题。
动态页面文件路径为:
pages └── dashboard └── seller └── [seller].tsx
页面核心代码如下:
import { useEffect } from "react"; import { useRouter } from "next/router"; import { hasCookie } from "cookies-next"; import Navbar from "@/components/Navbar"; import Sidebar from "@/components/Sidebar"; import { serverSideTranslations } from "next-i18next/serverSideTranslations"; import { useTranslation } from "next-i18next"; import { type Seller } from "../../../entities/seller"; import { getSellerProfile } from "@/services/seller/getProfile"; import { getAllSellers } from "@/services/seller/getAll"; import { sellerStore } from "@/hooks/sellerState"; import Update from "@/components/Forms/Seller/Update"; export async function getStaticPaths() { const data = await getAllSellers(); if (typeof data === "string") { return { paths: [], fallback: false }; } else { const paths = data.map((seller) => { return { params: { id: `${seller.id.toString()}`, // 此处存在参数名不匹配问题 }, }; }); return { paths, fallback: false }; } } function SellerProfile() { const router = useRouter(); const { t } = useTranslation("models"); const id = router.query.seller; useEffect(() => { if (hasCookie("authorization") === false) { router.push("/"); } }); const setName = sellerStore((state) => state.setName); const setAge = sellerStore((state) => state.setAge); const setLocation = sellerStore((state) => state.setLocation) useEffect(() => { const fetchData = async () => { const response: string | Seller = await getSellerProfile( id !== undefined ? +id : 0 ); if (typeof response === "string") { if (response === "Seller does not exist") { alert(t(response)) window.location.replace("/dashboard/models"); } else { alert(t(response)); } } else { const seller: Seller = response; setName(seller.name); setAge(seller.age); setLocation(seller.location) } }; fetchData(); }, []); // 缺少id依赖,路由切换时不会重新获取数据 return ( <body className="w-full h-full min-h-screen bg-gray-100 flex flex-row flex-nowrap"> <aside> <Sidebar /> </aside> <main className="w-full h-full"> <header className="w-full h-auto flex flex-row justify-end items-center"> <Navbar /> </header> <section className="w-full h-full flex flex-col justify-start items-start relative"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320" className="absolute" > <path fill="#581c87" fill-opacity="1" d="M0,256L24,224C48,192,96,128,144,117.3C192,107,240,149,288,144C336,139,384,85,432,96C480,107,528,181,576,229.3C624,277,672,299,720,261.3C768,224,816,128,864,85.3C912,43,960,53,1008,74.7C1056,96,1104,128,1152,133.3C1200,139,1248,117,1296,96C1344,75,1392,53,1416,42.7L1440,32L1440,0L1416,0C1392,0,1344,0,1296,0C1248,0,1200,0,1152,0C1104,0,1056,0,1008,0C960,0,912,0,864,0C816,0,768,0,720,0C672,0,624,0,576,0C528,0,480,0,432,0C384,0,336,0,288,0C240,0,192,0,144,0C96,0,48,0,24,0L0,0Z" ></path> </svg> <Update /> </section> </main> </body> ); } export async function getStaticProps({ locale }: any) { return { props: { ...(await serverSideTranslations(locale, [ "common", "navbar", "models", ])), }, }; } export default SellerProfile;
解决方案
1. 修正getStaticPaths的参数名匹配问题
动态页面文件名为[seller].tsx,意味着路由参数名应为seller,但当前getStaticPaths中返回的params使用的是id,这会导致Next.js无法正确匹配路由。修改getStaticPaths:
export async function getStaticPaths() { const data = await getAllSellers(); if (typeof data === "string") { return { paths: [], fallback: false }; } else { const paths = data.map((seller) => { return { params: { seller: `${seller.id.toString()}`, // 将id改为seller,匹配文件名中的参数名 }, }; }); return { paths, fallback: false }; } }
2. 调整fallback配置(可选)
如果卖家数据会在构建完成后新增,当前fallback: false会导致新的卖家ID访问时返回404。可以根据需求设置:
fallback: true:允许访问未预渲染的路径,在客户端异步生成页面fallback: 'blocking':服务器端渲染未预渲染的路径,生成后缓存
修改后:
return { paths, fallback: 'blocking' }; // 或true
3. 配置AWS EC2上的服务器重写规则
如果使用Nginx作为反向代理,需要确保所有请求都转发到Next.js的入口文件。在Nginx配置中添加:
location / { try_files $uri $uri/ /index.html; }
如果使用PM2运行Next.js生产服务器,确保服务器正确处理所有路由请求,Next.js默认生产服务器已支持,但额外反向代理需配置重写规则。
4. 修复useEffect依赖问题
当前获取数据的useEffect没有依赖id,从一个卖家页面跳转到另一个时不会重新获取数据。添加id作为依赖:
useEffect(() => { // ... 现有fetchData代码 }, [id]); // 添加id依赖
验证步骤
- 重新构建应用:
npm run build - 部署到AWS EC2
- 访问动态路由页面,确认404问题解决
内容的提问来源于stack exchange,提问作者pedrohrbarros
相关产品推荐
相关产品推荐

