部署Next.js应用到Vercel时遇replaceAll函数报错
问题:Next.js部署Vercel时replaceAll函数报错,本地构建正常
报错信息
Error occurred prerendering page "/". Read more: https://nextjs.org/docs/messages/prerender-error TypeError: match.replaceAll is not a function at /vercel/path0/.next/server/pages/index.js:321:30 at replaceString (/vercel/path0/node_modules/react-string-replace/index.js:81:17) at /vercel/path0/node_modules/react-string-replace/index.js:92:26 at Array.map (<anonymous>) at reactStringReplace (/vercel/path0/node_modules/react-string-replace/index.js:91:25) at renderDescription (/vercel/path0/.next/server/pages/index.js:320:56) at /vercel/path0/.next/server/pages/index.js:260:57 at Object.Ja [as useMemo] (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:27:240) at EventInfo (/vercel/path0/.next/server/pages/index.js:260:50)
简化后的组件代码
import React, { FC, useMemo } from "react"; import { GitHubEventsApi } from "../models/events.d"; import styles from "../../../styles/EventInfo.module.scss"; import reactStringReplace from "react-string-replace"; import { iconsObjFontello } from "../utils"; import { useInView } from "react-intersection-observer"; interface props { className?: string; type: GitHubEventsApi.EventType; repo: GitHubEventsApi.Repo; payload: GitHubEventsApi.Payload; createdAt: string; index?: number; } const EventInfo: FC<props> = ({ className, type, repo, createdAt, payload, index, }) => { const { ref, inView, entry } = useInView({ threshold: 0.2, }); const description = useMemo( () => renderDescription(type, repo, payload), [type, repo, payload] ); const url = useMemo( () => repo.url.replace("https://api.github.com/repos/", "https://github.com/"), [repo] ); const date = useMemo(() => Intl.DateTimeFormat("en-US", { day: "numeric", month: "short", year: "numeric", }).format(Date.parse(createdAt)), [createdAt]); return ( <div className={`${styles.eventInfo} ${inView ? styles.inView : ""}`} ref={ref} > <span className={styles.revealBlock}></span> <p className={`${styles.description}`}> {index} {description} <i className={iconsObjFontello[type]} /> </p> <span className={styles.revealBlock}></span> <p className={styles.description}> <a href={url} target="_blank"> {repo.name} </a> </p> <span className={styles.revealBlock}></span> <p className={styles.date}>{date}</p> </div> ); }; export default EventInfo; const renderDescription = ( type: GitHubEventsApi.EventType, repo: GitHubEventsApi.Repo, payload: GitHubEventsApi.Payload ) => { const linkToRepo = "<a href={repo.url}>{repo.name}</a>"; let description: React.ReactNodeArray; //add info from payload description = reactStringReplace( eventText[type], /{{(.*?)}}/g, (match, i) => { let removeBraces = match.replaceAll(/[{{}}]/g, ""); let split = removeBraces.split("."); return <span key={`${match}-${i}`}>{payload[split[1]]}</span>; } ); return description; };
解决办法
核心原因
replaceAll是ES2021新增的字符串方法,仅支持Node.js 15.0.0及以上版本。Vercel部署环境默认使用的Node.js版本可能低于该要求,而本地环境版本较高,因此出现本地正常、部署报错的差异。
具体解决方案
方案1:用replace替代replaceAll(最简方案)
你的正则表达式已经添加了g全局匹配标志,replace方法同样会替换所有匹配项,直接替换代码即可:
// 替换前 let removeBraces = match.replaceAll(/[{{}}]/g, ""); // 替换后 let removeBraces = match.replace(/[{{}}]/g, "");
方案2:指定Vercel的Node.js版本
在项目根目录创建.nvmrc文件,写入指定版本(如16.x):
16
或者在Vercel控制台的项目设置中,找到「General」→「Node.js Version」,选择16.x及以上的版本。
方案3:配置Next.js转译目标
在next.config.js中添加编译配置,确保转译不兼容的语法:
module.exports = { browserslist: [ '>0.3%', 'not ie 11', 'not dead', 'not op_mini all' ] };
方案4:添加polyfill兼容旧环境
如果必须保留replaceAll,可以安装并引入polyfill:
- 安装依赖:
npm install core-js
- 在
_app.js/_app.tsx顶部引入:
import 'core-js/es/string/replace-all';
内容的提问来源于stack exchange,提问作者João Pedro
相关产品推荐
相关产品推荐

