使用Next-translate时Next.js Vercel部署预渲染报错排查
Vercel部署Next.js项目构建报错排查
核心报错原因
本地生产环境运行正常但Vercel构建失败,本质是本地和Vercel构建环境的执行时序、运行环境差异导致,对应代码里有4处明确问题:
- 服务端渲染阶段非法访问浏览器API
代码中scrollToConciergerie方法直接调用window对象,两个触发点会在构建阶段的Node.js环境执行:一是外层useEffect未传依赖数组,渲染时会重复执行逻辑;二是给外层div绑定的onLoad事件本身不被div元素支持,服务端解析JSX时就会触发逻辑判断。Node环境不存在window全局对象,直接访问会直接抛构建错误。 - 翻译资源未做加载就绪判断
虽然从next-translate的useTranslation中解构了ready状态,但代码中未做任何拦截。Vercel构建时静态预渲染阶段翻译资源还未完成加载,t方法返回的conciergerieData不是预期数组,直接调用.map遍历会触发类型错误。本地环境因为资源加载速度快、热更新机制兜底,很难复现该问题。 - Next/Image组件配置不符合构建校验规则
自定义的myLoader直接拼接资源路径,若item.icon来自外部域名,且未在next.config.js中配置图片域名白名单,构建阶段的图片资源校验会直接失败。同时使用layout="fill"模式的Image组件,要求父元素必须有position: relative样式,当前父级span标签默认无定位属性,也会触发组件校验报错。 - App Router模式下未声明客户端组件(Next 13+版本特有问题)
如果项目使用Next.js 13及以上版本的App Router,页面默认是服务端组件,代码中用到了useState、useEffect、事件绑定等客户端API,未加'use client'声明会直接构建失败。
修复步骤
- 修复浏览器API访问问题
去掉外层div上无效的onLoad={scrollToConciergerie}属性,调整useEffect逻辑,增加环境判断和空依赖数组:useEffect(() => { if (typeof window === 'undefined') return const scrollToConciergerie = () => { window.scrollTo({ top: 300, behavior: "smooth", }); }; window.addEventListener("load", scrollToConciergerie); return () => { window.removeEventListener("load", scrollToConciergerie); }; }, []); - 修复翻译资源遍历的空值问题
在组件逻辑最前面增加就绪状态判断,同时给翻译返回值加空数组兜底:let { t, i18n, ready } = useTranslation("conciergerie", { useSuspense: true, }); // 翻译资源加载完成前返回兜底内容 if (!ready) return null const contentData = t( "conciergerieData", { count: 1 }, { returnObjects: true, } ) || []; - 修复Image组件配置
给Image组件的父级span标签增加position: relative样式,同时打开根目录next.config.js,配置图片资源白名单:
如果不需要Vercel自带的图片优化能力,可直接在images配置项中加/** @type {import('next').NextConfig} */ const nextConfig = { images: { // 替换为实际存放icon资源的域名 remotePatterns: [ { protocol: "https", hostname: "你的资源域名", }, ], }, }; module.exports = nextConfig;unoptimized: true关闭优化,跳过构建阶段的图片校验。 - 适配App Router(若使用)
如果页面放在App Router目录下,在文件最顶部增加'use client'声明,标记该组件为客户端组件。
内容的提问来源于stack exchange,提问作者Leo
相关产品推荐
相关产品推荐

