跳到主要内容

如何优化内存使用

随着应用程序的增长和功能变得更加丰富,它们在本地开发或创建生产构建时可能需要更多资源。

让我们探索一些策略和技术来优化内存并解决 Next.js 中的常见内存问题。

减少依赖项数量

具有大量依赖项的应用程序将使用更多内存。

包分析器可以帮助你调查应用程序中可能可以移除的大型依赖项,以提升性能和内存使用效率。

尝试 experimental.webpackMemoryOptimizations

v15.0.0 开始,您可以在 next.config.js 文件中添加 experimental.webpackMemoryOptimizations: true 来更改 Webpack 中的行为,这会减少最大内存使用,但可能会略微增加编译时间。

提示:此功能目前处于实验阶段,需要先在更多项目中测试,但被认为风险较低。

使用 --experimental-debug-memory-usage 运行 next build

14.2.0 开始,您可以运行 next build --experimental-debug-memory-usage 在 Next.js 将连续打印有关内存使用信息(如堆使用和垃圾收集统计信息)的模式下运行构建。当内存使用接近配置的限制时,也会自动拍摄堆快照。

提示:此功能与 Webpack 构建工作器选项不兼容,除非您有自定义 webpack 配置,否则该选项会自动启用。

记录堆配置文件

要查找内存问题,您可以从 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 中,您可以打开内存选项卡并点击"加载配置文件"按钮来可视化文件。

分析堆的快照

您可以使用检查器工具来分析应用程序的内存使用情况。

运行 next buildnext dev 命令时,在命令开头添加 NODE_OPTIONS=--inspect。这将在默认端口上公开检查器代理。 如果您希望在任何用户代码开始之前中断,可以传递 --inspect-brk。当进程运行时,您可以使用 Chrome DevTools 等工具连接到调试端口来记录和分析堆的快照,以查看保留了什么内存。

14.2.0 开始,您还可以使用 --experimental-debug-memory-usage 标志运行 next build 以更容易拍摄堆快照。

在此模式下运行时,您可以随时向进程发送 SIGUSR2 信号,进程将拍摄堆快照。

堆快照将保存到 Next.js 应用程序的项目根目录,并可以在任何堆分析器(如 Chrome DevTools)中加载,以查看保留了什么内存。此模式与 Webpack 构建工作器还不兼容。

查看如何记录和分析堆快照以获取更多信息。

Webpack 构建工作器

Webpack 构建工作器允许您在单独的 Node.js 工作器中运行 Webpack 编译,这将减少构建期间应用程序的内存使用。

如果您的应用程序从 v14.1.0 开始没有自定义 Webpack 配置,则默认启用此选项。

如果您使用的是较旧版本的 Next.js 或有自定义 Webpack 配置,可以通过在 next.config.js 中设置 experimental.webpackBuildWorker: true 来启用此选项。

提示:此功能可能与所有自定义 Webpack 插件不兼容。

禁用 Webpack 缓存

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',
})
}
// 重要:返回修改后的配置
return config
},
}

export default nextConfig

禁用静态分析

类型检查和 linting 可能需要大量内存,特别是在大型项目中。 但是,大多数项目都有专门的 CI 运行器已经处理这些任务。 当构建在"Linting 和检查类型有效性"步骤期间产生内存不足问题时,您可以在构建期间禁用这些任务:

next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
eslint: {
// 警告:这允许生产构建成功完成,即使
// 您的项目有 ESLint 错误。
ignoreDuringBuilds: true,
},
typescript: {
// !! 警告 !!
// 危险地允许生产构建成功完成,即使
// 您的项目有类型错误。
// !! 警告 !!
ignoreBuildErrors: true,
},
}

export default nextConfig

请记住,由于类型错误或 linting 问题,这可能会产生错误的部署。 我们强烈建议只有在静态分析完成后才将构建提升到生产环境。 如果您部署到 Vercel,可以查看分阶段部署指南以了解如何在自定义任务成功后将构建提升到生产环境。

禁用源映射

生成源映射在构建过程中消耗额外的内存。

您可以通过在 Next.js 配置中添加 productionBrowserSourceMaps: falseexperimental.serverSourceMaps: false 来禁用源映射生成。

提示:某些插件可能会打开源映射,可能需要自定义配置来禁用。

Edge 内存问题

Next.js v14.1.3 修复了使用 Edge 运行时时的内存问题。请更新到此版本(或更高版本)以查看是否解决了您的问题。

预加载条目

当 Next.js 服务器启动时,它会将每个页面的 JavaScript 模块预加载到内存中,而不是在请求时加载。

此优化允许更快的响应时间,以换取更大的初始内存占用。

要禁用此优化,请将 experimental.preloadEntriesOnStart 标志设置为 false

next.config.ts
import type { NextConfig } from 'next'

const config: NextConfig = {
experimental: {
preloadEntriesOnStart: false,
},
}

export default config

Next.js 不会卸载这些 JavaScript 模块,这意味着即使禁用此优化,如果最终请求所有页面,您的 Next.js 服务器的内存占用最终将是相同的。