跳到內容
App Router指南記憶體使用

如何最佳化記憶體使用

隨著應用程式的增長和功能日益豐富,在本地開發或建立生產構建時,它們可能會需要更多的資源。

讓我們探索一些策略和技術來最佳化記憶體並解決 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 構建時,將 --heap-prof 標誌傳遞給 Node.js。

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',
      })
    }
    // Important: return the modified config
    return config
  },
}
 
export default nextConfig

停用靜態分析

型別檢查可能需要大量記憶體,尤其是在大型專案中。但是,大多數專案都有一個專用的 CI 執行器,它已經處理這些任務。當構建在“執行 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

請記住,這可能會因為型別錯誤而導致部署失敗。我們強烈建議僅在靜態分析完成後將構建推向生產環境。如果您部署到 Vercel,您可以查閱部署暫存指南,瞭解如何在自定義任務成功後將構建推向生產環境。

停用源對映

在構建過程中生成源對映會消耗額外的記憶體。

您可以透過在 Next.js 配置中新增 productionBrowserSourceMaps: falseexperimental.serverSourceMaps: false 來停用源對映生成。

當使用 cacheComponents 功能時,Next.js 在 next build 的預渲染階段預設使用源對映。如果您在該階段(“生成靜態頁面”之後)持續遇到記憶體問題,您可以嘗試透過在 Next.js 配置中新增 enablePrerenderSourceMaps: 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 伺服器的記憶體佔用最終也會相同。