应用不断增长、功能变得更丰富时,本地开发和生产构建可能需要更多资源。下面介绍优化内存使用、排查 Next.js 常见内存问题的一些策略和方法。
减少依赖数量
依赖很多的应用会使用更多内存。Bundle Analyzer 可以帮助查找大型依赖,评估是否能够移除它们,以改善性能和内存占用。
尝试 experimental.webpackMemoryOptimizations
从 v15.0.0 开始,可以在 next.config.js 中添加 experimental.webpackMemoryOptimizations: true。这会改变 Webpack 的行为,降低峰值内存占用,但可能略微增加编译时间。
此功能仍处于实验阶段,以便先在更多项目上测试。官方将其描述为风险较低的实验功能;实际项目效果仍需验证。
运行带内存调试参数的构建
从 14.2.0 开始,可以运行 next build --experimental-debug-memory-usage。在该模式下,Next.js 会在整个构建过程中持续输出内存信息,包括堆使用量和垃圾回收统计。内存使用接近配置上限时,也会自动生成堆快照。
此功能不兼容 Webpack build worker。没有自定义 Webpack 配置时,build worker 通常会自动启用。
记录堆分析文件
可以让 Node.js 记录堆分析文件,再加载到 Chrome DevTools 中,寻找可能的内存泄漏来源。
启动 Next.js 构建时,在终端给 Node.js 传入 --heap-prof:
node --heap-prof node_modules/next/dist/bin/next build
构建结束后,Node.js 会创建一个 .heapprofile 文件。在 Chrome DevTools 中打开 Memory 标签,点击 “Load Profile” 加载并查看文件。
分析堆快照
可以使用调试检查工具分析应用的内存占用。运行 next build 或 next dev 时,在命令前加上 NODE_OPTIONS=--inspect,会在默认端口启用 inspector agent。如果希望在任何用户代码运行前暂停,可改用 --inspect-brk。进程运行期间,可用 Chrome DevTools 等工具连接调试端口,记录和分析堆快照,了解哪些内存仍被保留。
从 14.2.0 开始,也可以给 next build 加上 --experimental-debug-memory-usage,更方便地获取堆快照。在该模式下,可以随时向进程发送 SIGUSR2 信号,让进程保存堆快照。快照文件会写入 Next.js 项目的根目录,可以加载到 Chrome DevTools 等堆分析工具中查看。此模式目前还不兼容 Webpack build worker。
更多说明见 记录与分析堆快照。调试端口与堆文件可能包含应用内部数据,使用时应限定可访问范围;不同操作系统对环境变量和信号的支持需要按实际运行环境核查。
Webpack build worker
Webpack build worker 可以在独立的 Node.js worker 中执行 Webpack 编译,降低构建时应用的内存使用量。从 v14.1.0 开始,没有自定义 Webpack 配置的应用会默认启用此选项。
使用更旧的 Next.js 版本或自定义 Webpack 配置时,可以在 next.config.js 中设置 experimental.webpackBuildWorker: true 启用它。
此功能可能不兼容某些自定义 Webpack 插件。上面的 Webpack 选项不应直接视为 Turbopack 的配置。
关闭 Webpack 缓存
Webpack 缓存会把生成的模块保存在内存或磁盘中,提升构建速度;但保存缓存也会增加内存占用。可以通过自定义 Webpack 配置改变这一行为:
next.config.mjs:
/** @type {import('next').NextConfig} */
const nextConfig = {
webpack: (
config,
{ buildId, dev, isServer, defaultLoaders, nextRuntime, webpack }
) => {
if (config.cache && !dev) {
config.cache = Object.freeze({
type: 'memory',
})
}
// Important: return the modified config
return config
},
}
export default nextConfig
此示例把生产构建缓存调整为内存类型,并未让所有 Webpack 缓存彻底消失。标题沿用原文,应以代码实际行为为准;修改配置后必须返回 config。
关闭构建期间的静态分析
类型检查可能使用大量内存,尤其是在大型项目中。不过,许多项目已有专门的 CI runner 执行这些任务。如果构建在 “Running TypeScript” 阶段发生内存耗尽,可以在构建期间关闭该任务:
next.config.mjs:
/** @type {import('next').NextConfig} */
const nextConfig = {
typescript: {
// !! WARN !!
// Dangerously allow production builds to successfully complete even if
// your project has type errors.
// !! WARN !!
ignoreBuildErrors: true,
},
}
export default nextConfig
参见 Ignoring TypeScript Errors。这样可能把存在类型错误的版本部署出去。强烈建议只有静态分析完成后,才把构建提升到生产环境。使用 Vercel 时,可参考暂存与生产部署指南,在自定义检查成功后再提升构建。
关闭 source map
构建时生成 source map 会消耗额外内存。可以在 Next.js 配置中加入 productionBrowserSourceMaps: false 与 experimental.serverSourceMaps: false,关闭相应的 source map 生成。
Next.js 默认在 next build 的预渲染阶段使用 source map。如果总是在该阶段,也就是 “Generating static pages” 之后遇到内存问题,可以尝试加入 enablePrerenderSourceMaps: false,在这一阶段关闭 source map。
某些插件会开启 source map,可能需要分别修改其配置。
Edge 内存问题
Next.js v14.1.3 修复了一个 Edge runtime 内存问题。可以更新到该版本或更新版本,检查是否解决了你遇到的问题。
预加载入口
Next.js 服务器启动时会把各页面的 JavaScript 模块预加载到内存中,而不是等到收到请求时再加载。这样可以缩短响应时间,但启动时的内存占用更高。
要关闭此优化,把 experimental.preloadEntriesOnStart 设为 false。
TypeScript,next.config.ts:
import type { NextConfig } from 'next'
const config: NextConfig = {
experimental: {
preloadEntriesOnStart: false,
},
}
export default config
JavaScript,next.config.mjs:
/** @type {import('next').NextConfig} */
const config = {
experimental: {
preloadEntriesOnStart: false,
},
}
export default config
Next.js 不会卸载这些 JavaScript 模块。因此,即使关闭了预加载,如果所有页面最终都被访问,服务器最终的内存占用仍会达到同样的水平。











暂无评论内容