部署

恭喜,是時候將產品上線了。

您可以選擇 使用 Vercel 託管 Next.js,或自架主機在 Node.js 伺服器、Docker 映像,甚至是靜態 HTML 檔案上。當使用 next start 部署時,所有 Next.js 功能都受到支援。

生產環境建置

執行 next build 會為您的應用程式生成一個針對生產環境優化的版本。HTML、CSS 和 JavaScript 檔案會根據您的頁面生成。JavaScript 會被 編譯,瀏覽器套件會使用 Next.js 編譯器 進行 最小化,以幫助實現最佳效能並支援 所有現代瀏覽器

Next.js 產生一個標準的部署輸出,供託管和自架主機的 Next.js 使用。這確保所有功能在兩種部署方法中都受到支援。在下一個主要版本中,我們將把此輸出轉換為我們的 建置輸出 API 規格

使用 Vercel 託管 Next.js

Vercel,Next.js 的創建者和維護者,為您的 Next.js 應用程式提供託管基礎設施和開發者體驗平台。

部署到 Vercel 是零配置的,並提供全球範圍內的可擴展性、可用性和效能的額外增強。然而,所有 Next.js 功能在自架主機時仍然受到支援。

了解更多關於 Next.js on Vercel免費部署模板 來試用。

自架主機

您可以通過三種不同的方式自架主機 Next.js:

Node.js 伺服器

Next.js 可以部署到任何支援 Node.js 的託管供應商。確保您的 package.json 中有 "build""start" 腳本:

package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  }
}

然後,執行 npm run build 來建置您的應用程式。最後,執行 npm run start 來啟動 Node.js 伺服器。此伺服器支援所有 Next.js 功能。

Docker 映像

Next.js 可以部署到任何支援 Docker 容器的託管供應商。當部署到容器編排平台如 Kubernetes 或在任何雲端供應商中運行容器時,可以使用此方法。

  1. 安裝 Docker 在您的機器上
  2. 克隆我們的範例 (或 多環境範例)
  3. 建置您的容器:docker build -t nextjs-docker .
  4. 運行您的容器:docker run -p 3000:3000 nextjs-docker

通過 Docker 的 Next.js 支援所有 Next.js 功能。

靜態 HTML 匯出

Next.js 允許從靜態網站或單頁應用程式 (SPA) 開始,然後稍後選擇性地升級使用需要伺服器的功能。

由於 Next.js 支援此 靜態匯出,它可以部署並託管在任何能夠提供 HTML/CSS/JS 靜態資源的網頁伺服器上。這包括 AWS S3、Nginx 或 Apache 等工具。

作為 靜態匯出 運行不支援需要伺服器的 Next.js 功能。了解更多

須知:

功能

圖片優化

通過 next/image圖片優化 在使用 next start 部署時自架主機零配置即可工作。如果您希望有一個獨立的服務來優化圖片,您可以 配置圖片載入器

圖片優化可以與 靜態匯出 一起使用,通過在 next.config.js 中定義自訂圖片載入器。請注意,圖片是在運行時優化,而不是在建置時。

須知:

  • 自架主機時,考慮安裝 sharp 以在生產環境中獲得更高性能的 圖片優化,通過在您的專案目錄中運行 npm install sharp。在 Linux 平台上,sharp 可能需要 額外配置 以防止過多的記憶體使用。
  • 了解更多關於 優化圖片的快取行為 以及如何配置 TTL。
  • 您也可以 禁用圖片優化 並仍然保留使用 next/image 的其他好處,如果您願意。例如,如果您自己單獨優化圖片。

中介軟體

中介軟體 在使用 next start 部署時自架主機零配置即可工作。由於它需要存取傳入請求,因此在使用 靜態匯出 時不受支援。

中介軟體使用一個 運行時,它是所有可用 Node.js API 的子集,以幫助確保低延遲,因為它可能在您的應用程式中每個路由或資源前運行。此運行時不需要“在邊緣”運行,並且在單一區域伺服器中工作。需要額外的配置和基礎設施來在多個區域中運行中介軟體。

如果您希望新增邏輯(或使用外部套件)需要所有 Node.js API,您可能可以將此邏輯移動到 佈局 作為 伺服器元件。例如,檢查 標頭重新導向。您也可以使用標頭、cookie 或查詢參數通過 next.config.js重新導向重寫。如果這不起作用,您也可以使用 自訂伺服器

環境變數

Next.js 可以支援建置時和運行時環境變數。

預設情況下,環境變數僅在伺服器上可用。要將環境變數暴露給瀏覽器,必須以 NEXT_PUBLIC_ 為前綴。然而,這些公共環境變數將在 next build 期間內聯到 JavaScript 套件中。

要讀取運行時環境變數,我們建議使用 getServerSideProps逐步採用應用程式路由。使用應用程式路由,我們可以在動態渲染期間安全地在伺服器上讀取環境變數。這允許您使用一個單一的 Docker 映像,可以在多個環境中推廣,並使用不同的值。

import { unstable_noStore as noStore } from 'next/cache';

export default function Component() {
  noStore();
  // cookies(), headers(), 和其他動態函數
  // 也會選擇動態渲染,使
  // 此環境變數在運行時評估
  const value = process.env.MY_VALUE
  ...
}

須知:

  • 您可以使用 register 函數 在伺服器啟動時運行代碼。
  • 我們不建議使用 runtimeConfig 選項,因為這不適用於獨立輸出模式。相反,我們建議 逐步採用 應用程式路由。

快取和 ISR

Next.js 可以快取回應、生成的靜態頁面、建置輸出和其他靜態資源,如圖片、字體和腳本。

快取和重新驗證頁面(使用增量靜態重新生成 (ISR) 或應用程式路由中的新功能)使用 相同的共享快取。預設情況下,此快取儲存在您的 Next.js 伺服器的檔案系統(磁碟上)。這在自架主機時自動工作,同時支援頁面和應用程式路由。

您可以配置 Next.js 快取位置,如果您希望將快取的頁面和數據持久化到持久儲存,或在多個容器或 Next.js 應用程式實例之間共享快取。

自動快取

  • Next.js 設置 Cache-Control 標頭為 public, max-age=31536000, immutable 給真正不可變的資源。這不能被覆蓋。這些不可變檔案在檔案名稱中包含 SHA 哈希,因此可以安全地無限快取。例如,靜態圖片匯入。您可以 配置 TTL 給圖片。
  • 增量靜態重新生成 (ISR) 設置 Cache-Control 標頭為 s-maxage: <revalidate in getStaticProps>, stale-while-revalidate。此重新驗證時間在您的 getStaticProps 函數 中以秒為單位定義。如果您設置 revalidate: false,它將預設為一年的快取持續時間。
  • 動態渲染的頁面設置 Cache-Control 標頭為 private, no-cache, no-store, max-age=0, must-revalidate 以防止使用者特定數據被快取。這適用於應用程式路由和頁面路由。這也包括 草稿模式

靜態資源

如果您希望將靜態資源託管在不同的網域或 CDN 上,您可以在 next.config.js 中使用 assetPrefix 配置。Next.js 將在檢索 JavaScript 或 CSS 檔案時使用此資源前綴。將您的資源分離到不同的網域會帶來 DNS 和 TLS 解析的額外時間的缺點。

了解更多關於 assetPrefix

配置快取

預設情況下,生成的快取資源將儲存在記憶體中(預設為 50mb)和磁碟上。如果您使用容器編排平台如 Kubernetes 託管 Next.js,每個 pod 將有一份快取的副本。為防止顯示過時的數據,因為快取預設不在 pod 之間共享,您可以配置 Next.js 快取以提供快取處理程序並禁用記憶體快取。

要在自架主機時配置 ISR/數據快取位置,您可以在 next.config.js 檔案中配置自訂處理程序:

next.config.js
module.exports = {
  cacheHandler: require.resolve('./cache-handler.js'),
  cacheMaxMemorySize: 0, // 禁用預設的記憶體快取
}

然後,在您的專案根目錄中建立 cache-handler.js,例如:

cache-handler.js
const cache = new Map()

module.exports = class CacheHandler {
  constructor(options) {
    this.options = options
  }

  async get(key) {
    // 這可以儲存在任何地方,如持久儲存
    return cache.get(key)
  }

  async set(key, data, ctx) {
    // 這可以儲存在任何地方,如持久儲存
    cache.set(key, {
      value: data,
      lastModified: Date.now(),
      tags: ctx.tags,
    })
  }

  async revalidateTag(tag) {
    // 遍歷快取中的所有條目
    for (let [key, value] of cache) {
      // 如果值的標籤包含指定的標籤,刪除此條目
      if (value.tags.includes(tag)) {
        cache.delete(key)
      }
    }
  }
}

使用自訂快取處理程序將允許您確保所有託管您的 Next.js 應用程式的 pod 之間的一致性。例如,您可以將快取值儲存在任何地方,如 Redis 或 AWS S3。

須知:

  • revalidatePath 是快取標籤上的一個便利層。呼叫 revalidatePath 將使用提供的頁面的特殊預設標籤呼叫 revalidateTag 函數。

建置快取

Next.js 在 next build 期間生成一個 ID 來識別正在提供的應用程式版本。相同的建置應該被使用並在多個容器中啟動。

如果您為環境的每個階段重新建置,您將需要生成一個一致的建置 ID 以在容器之間使用。在 next.config.js 中使用 generateBuildId 命令:

next.config.js
module.exports = {
  generateBuildId: async () => {
    // 這可以是任何東西,使用最新的 git 哈希
    return process.env.GIT_HASH
  },
}

版本偏差

Next.js 將自動緩解大多數 版本偏差 的情況,並在檢測到時自動重新載入應用程式以檢索新資源。例如,如果 deploymentId 不匹配,頁面之間的轉換將執行硬導航而不是使用預取的值。

當應用程式重新載入時,如果未設計為在頁面導航之間持久化,可能會丟失應用程式狀態。例如,使用 URL 狀態或本地儲存將在頁面刷新後持久化狀態。然而,像 useState 這樣的元件狀態將在此類導航中丟失。

Vercel 為 Next.js 應用程式提供額外的 偏差保護,以確保舊客戶端仍然可以存取來自先前版本的資源和函數,即使在部署新版本之後。

您可以手動在 next.config.js 檔案中配置 deploymentId 屬性,以確保每個請求使用 ?dpl 查詢字符串或 x-deployment-id 標頭。

手動優雅關機

當自行託管服務時,您可能希望在伺服器收到 SIGTERMSIGINT 信號關閉時執行特定程式碼。

您可以將環境變數 NEXT_MANUAL_SIG_HANDLE 設為 true,然後在 _document.js 檔案中為該信號註冊處理程序。請注意,您需要直接在 package.json 的 scripts 中註冊環境變數,而不是在 .env 檔案中。

須知事項:手動信號處理在 next dev 模式下不可用。

package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "NEXT_MANUAL_SIG_HANDLE=true next start"
  }
}
pages/_document.js
if (process.env.NEXT_MANUAL_SIG_HANDLE) {
  process.on('SIGTERM', () => {
    console.log('Received SIGTERM: cleaning up')
    process.exit(0)
  })
  process.on('SIGINT', () => {
    console.log('Received SIGINT: cleaning up')
    process.exit(0)
  })
}

On this page