跳至內容

部署

恭喜,是時候部署到正式環境了。

您可以使用 Vercel 部署 Managed 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

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

部署到 Vercel 是零設定的,並提供額外的增強功能,以提升全球的擴展性、可用性和效能。然而,所有 Next.js 功能在自行託管時仍然受到支援。

深入瞭解 Vercel 上的 Next.js免費部署範本 來試用看看。

自行託管

您可以透過三種不同的方式自行託管 Next.js

🎥 觀看影片:深入瞭解 Next.js 自我託管 → YouTube (45 分鐘)

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 start 部署時,透過 next/image 進行的圖片最佳化可在自行託管的情況下運作,無需任何設定。如果您希望使用個別的服務來最佳化圖片,您可以設定圖片載入器

圖片最佳化可以與靜態匯出一起使用,方法是在 next.config.js 中定義自訂圖片載入器。請注意,圖片是在執行時期最佳化的,而不是在建置期間。

注意事項

  • 在基於 glibc 的 Linux 系統上,圖片最佳化可能需要額外設定,以防止過度使用記憶體。
  • 深入瞭解最佳化圖片的快取行為,以及如何設定 TTL。
  • 如果您願意,您也可以停用圖片最佳化,同時仍然保留使用 next/image 的其他優點。例如,如果您是自己另外最佳化圖片的話。

中介軟體

使用 next start 部署時,中間件 (Middleware) 可在自行託管的環境中零設定運作。由於中間件需要存取傳入的請求,因此在使用 靜態匯出 (Static Export) 時不受支援。

中間件使用所有可用 Node.js API 的子集作為 執行環境 (Runtime),以確保低延遲,因為它可能在應用程式中的每個路由或資源之前執行。此執行環境不需要在「邊緣」運行,並且可以在單一區域的伺服器上運作。若要在多個區域運行中間件,則需要額外的設定和基礎架構。

如果您要新增需要所有 Node.js API 的邏輯(或使用外部套件),您可以將此邏輯作為 伺服器元件 (Server Component) 移至 佈局 (Layout) 中。例如,檢查 標頭 (Headers) 和執行 重新導向 (Redirecting)。您也可以使用標頭、Cookie 或查詢參數,透過 next.config.js 進行 重新導向重寫 (Rewrite)。如果這些方法都無效,您也可以使用 自訂伺服器 (Custom Server)

環境變數

Next.js 支援建置時和執行時的環境變數。

預設情況下,環境變數僅在伺服器端可用。要將環境變數公開給瀏覽器,必須加上 NEXT_PUBLIC_ 前綴。然而,這些公開的環境變數會在 next build 期間被嵌入到 JavaScript 捆綁包中。

您可以在動態渲染期間安全地在伺服器端讀取環境變數。

app/page.ts
import { connection } from 'next/server'
 
export default async function Component() {
  await connection()
  // cookies, headers, and other Dynamic APIs
  // will also opt into dynamic rendering, meaning
  // this env variable is evaluated at runtime
  const value = process.env.MY_VALUE
  // ...
}

這讓您可以使用單個 Docker 映像,並透過具有不同值的多個環境進行升級。

注意事項

  • 您可以使用 register 函式 在伺服器啟動時執行程式碼。
  • 我們不建議使用 runtimeConfig 選項,因為它不適用於獨立輸出模式。相反地,我們建議逐步採用 App Router。

快取和 ISR

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

快取和重新驗證頁面(使用 增量靜態再生 (Incremental Static Regeneration, ISR))使用相同的共用快取。預設情況下,此快取儲存在 Next.js 伺服器上的檔案系統(磁碟)中。在使用 Pages Router 和 App Router 自行託管時,這會自動運作

如果您想要將快取的頁面和資料保存到持久儲存區,或是在多個容器或 Next.js 應用程式的執行個體之間共用快取,您可以設定 Next.js 快取位置。

自動快取

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

靜態資源 設定。Next.js 在擷取 JavaScript 或 CSS 檔案時將會使用此資源前綴。將您的資源分離到不同的網域確實會帶來額外的 DNS 和 TLS 解析時間的缺點。

深入了解 assetPrefix.

設定快取
next.config.js
module.exports = {
  cacheHandler: require.resolve('./cache-handler.js'),
  cacheMaxMemorySize: 0, // disable default in-memory caching
}

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

cache-handler.js
const cache = new Map()
 
module.exports = class CacheHandler {
  constructor(options) {
    this.options = options
  }
 
  async get(key) {
    // This could be stored anywhere, like durable storage
    return cache.get(key)
  }
 
  async set(key, data, ctx) {
    // This could be stored anywhere, like durable storage
    cache.set(key, {
      value: data,
      lastModified: Date.now(),
      tags: ctx.tags,
    })
  }
 
  async revalidateTag(tags) {
    // tags is either a string or an array of strings
    tags = [tags].flat()
    // Iterate over all entries in the cache
    for (let [key, value] of cache) {
      // If the value's tags include the specified tag, delete this entry
      if (value.tags.some((tag) => tags.include(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 () => {
    // This could be anything, using the latest git hash
    return process.env.GIT_HASH
  },
}

版本偏移

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

當應用程式重新載入時,如果應用程式未設計為在頁面導航之間保留狀態,則可能會遺失應用程式狀態。例如,使用 URL 狀態或本地儲存空間會在頁面重新整理後保留狀態。但是,像 useState 這樣的元件狀態將會在這種導航中遺失。

Vercel 為 Next.js 應用程式提供了額外的 偏移保護,以確保即使在新版本部署後,舊版用戶仍可使用先前版本的資源和函式。

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

串流與懸念

Next.js App Router 在自行託管時支援串流回應。如果您使用的是 Nginx 或類似的代理伺服器,您需要將其配置為停用緩衝才能啟用串流。

例如,您可以透過將 Nginx 中的 X-Accel-Buffering 設定為 no 來停用緩衝。

next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/:path*{/}?',
        headers: [
          {
            key: 'X-Accel-Buffering',
            value: 'no',
          },
        ],
      },
    ]
  },
}

部分預渲染 部分預渲染(實驗性)在 Next.js 中預設即可運作,並不是 CDN 的功能。這包含以 Node.js 伺服器部署(透過 next start)以及使用 Docker 容器時。

搭配 CDN 使用

在 Next.js 應用程式前端使用 CDN 時,當存取動態 API 時,頁面將包含 Cache-Control: private 回應標頭。這可確保產生的 HTML 頁面被標記為不可快取。如果頁面已完全預渲染為靜態,則會包含 Cache-Control: public,以允許頁面在 CDN 上快取。

如果您不需要混合使用靜態和動態組件,您可以將整個路由設為靜態,並將輸出 HTML 快取在 CDN 上。如果未使用動態 API,則在執行 next build 時,此自動靜態優化是預設行為。

上線檢查清單

在將 Next.js 應用程式正式上線之前,建議您參考這些建議以確保最佳效能和使用者體驗。

靜態匯出

Next.js 讓您可以從靜態網站或單頁應用程式 (SPA) 開始,之後再選擇性地升級以使用需要伺服器的功能。

多區域

瞭解如何使用 Next.js 多區域建置微前端,以便在單一網域下部署多個 Next.js 應用程式。