分享方式:


在 Azure Static Web Apps 上部署混合式 Next.js 網站 (預覽)

在本教學課程中,您將了解如何使用針對 React Server 元件、伺服器端轉譯 (SSR) 和 API 路由等 Next.js 功能的支援,將 Next.js 網站部署至 Azure Static Web Apps

注意

Next.js 混合式支援處於預覽。

必要條件

資源 描述
Azure 帳戶 如果您沒有具有作用中訂用帳戶的 Azure 帳戶,您可以免費建立帳戶
GitHub 帳戶 如果您沒有 GitHub 帳戶,您可以免費建立帳戶
Node.js 安裝最新版本的 Node.js。
Next.js CLI 安裝最新版本的 Next.js CLI。 如需詳細資料,請參閱 Next.js 使用者入門指南

預覽中不支援的功能

具有混合式轉譯的 Next.js 不支援 Static Web Apps 的下列功能:

  • 選取 Azure 服務:使用 Azure Functions、Azure App Service、Azure 容器應用程式或 Azure API 管理連結的 API。
  • SWA CLI 功能:SWA CLI 本機模擬和部署。
  • 部分功能支援:不支援 staticwebapp.config.json 檔案中的下列屬性:
    • 不支援導覽後援。
    • 必須在 next.config.js 內設定對 Next.js 應用程式內路由的路由重寫。
    • staticwebapp.config.json 檔案內的設定會優先於 next.config.js 內的設定。
    • 應使用 next.config.js 處理 Next.js 網站的設定,以取得完整的功能相容性。
  • 跳過建置Azure/static-web-apps-deploy@v1 部署映像中不支援 skip_app_buildskip_api_build 功能。
  • 增量靜態重新產生 (ISR):不支援影像快取。

注意

混合式 Next.js 應用程式的最大應用程式大小為 250 MB。 使用 Next.js 的獨立功能來取得最佳化的應用程式大小。 如果這還不夠,如果您的應用程式大小需求超過 250 MB,請考慮使用靜態 HTML 匯出的 Next.js

建立存放庫

本文使用 GitHub 範本存放庫,讓您可以輕鬆地開始使用。 範本具有可部署至 Azure Static Web Apps 的入門應用程式。

  1. 瀏覽至下列位置以建立新的存放庫。

    https://github.com/staticwebdev/nextjs-hybrid-starter/generate

  2. 將您的存放庫命名為 my-first-static-web-app

  3. 選取 [從範本建立存放庫]

    從範本按鈕建立存放庫的螢幕擷取畫面。

建立靜態 Web 應用程式

現在已建立存放庫,您可以從 Azure 入口網站建立靜態 Web 應用程式。

  1. 前往 Azure 入口網站
  2. 選取 [建立資源]
  3. 搜尋 Static Web Apps
  4. 選取 [Static Web Apps]
  5. 選取 建立

在基本資料區段中,先設定您的新應用程式,並將其連結至 GitHub 存放庫。

Azure 入口網站中 [基本] 區段的螢幕擷取畫面。

設定
訂用帳戶 選取 Azure 訂閱。
資源群組 選取 [建立新的] 連結,然後在文字方塊中輸入 static-web-apps-test
名稱 在文字方塊中輸入 my-first-static-web-app
方案類型 選取 [免費]
來源 選取 [GitHub],並視需要登入 GitHub。

選取 [使用 GitHub 登入],並使用 GitHub 進行驗證。

當您使用 GitHub 登入後,請輸入存放庫資訊。

設定
組織 選取您的組織。
存放庫 選取 [my-first-web-static-app]
分支 選取 [主要]

Azure 入口網站中存放庫詳細資料的螢幕擷取畫面。

注意

如果您沒有看到任何存放庫:

  • 您可能需要在 GitHub 中授權 Azure Static Web Apps。 瀏覽至您的 GitHub 存放庫,並移至 [設定] > [應用程式] > [授權的 OAuth 應用程式],選取 [Azure Static Web Apps],然後選取 [授與]
  • 您可能需要在 Azure DevOps 組織中授權 Azure Static Web Apps。 您必須是組織的擁有者,才能授與權限。 透過 OAuth 要求第三方應用程式存取。 如需詳細資訊,請參閱使用 OAuth 2.0授權 REST API 的存取

在組建詳細資料區段中,新增您慣用前端架構的特定設定詳細資料。

  1. 從 [組建預設] 下拉式清單選取 [Next.js]

  2. 保留 [應用程式位置] 方塊中的預設值。

  3. 將 [API 位置] 方塊保留為空白。

  4. 將 [應用程式成品位置] 方塊保留為空白。

選取 [檢閱 + 建立]。

[建立] 按鈕的螢幕擷取畫面。

檢視網站

部署靜態應用程式有兩個層面。 第一個層面會建立構成您應用程式的基礎 Azure 資源。 第二個層面是會建置及發佈您的應用程式的工作流程。

在您可以移至新的靜態網站之前,部署建置必須先完成執行。

Static Web Apps [概觀] 視窗會顯示一系列的連結,協助您與 Web 應用程式互動。

Azure Static Web Apps [概觀] 視窗的螢幕擷取畫面。

選取顯示「選取這裡檢查您的 GitHub Actions 執行狀態」的橫幅,會帶您前往針對您存放庫執行的 GitHub Actions。 一旦您確認部署作業已完成,您就可以透過產生的 URL 以移至您的網站。

GitHub Actions 工作流程完成之後,您可以選取 URL 連結,在新索引標籤中開啟網站。

在本機設定您的 Next.js 專案以進行變更

  1. 將新的存放庫複製到您的機器。 請務必將 <GITHUB_ACCOUNT_NAME> 取代為您的帳戶名稱。

    git clone http://github.com/<GITHUB_ACCOUNT_NAME>/my-first-static-web-app
    
  2. 在 Visual Studio Code 或您慣用的程式碼編輯器中開啟專案。

設定伺服器端轉譯

受控後端會自動提供所有方案中的每個混合式 Next.js 部署使用。 不過,您可以將自訂後端指派給您的網站,以微調效能並更充分掌控後端。 如果您從受控後端與連結的後端之間切換,則您的網站不會停機。

使用自己的後端

使用自己的後端時,您可以改善效能,並更充分地控制 Next.js 伺服器端轉譯。 使用下列步驟來設定網站的自訂後端。

以下步驟說明如何將自訂後端與您的標準方案和更高方案的靜態 Web 應用程式相關聯。

注意

連結後端僅供使用標準方案或以上版本的網站使用。

  1. 移至 Azure 入口網站中的靜態 Web 應用程式。

  2. 選取 [設定],然後從側邊功能表選取 [API]

  3. 選取 [設定連結的後端]

  4. 建立新的 App Service 方案,或選取現有的 App Service 方案。

    您選取的 App Service 方案至少必須使用 S1 SKU。

  5. 按一下 [連結]

使用伺服器元件新增伺服器轉譯的資料

若要使用應用程式路由器在 Next.js 專案中新增伺服器轉譯的資料,請編輯 Next.js 元件以新增伺服器端作業,以便轉譯元件中的資料。 根據預設,Next.js 元件是可以是伺服器轉譯的伺服器元件

  1. 開啟 app/page.tsx 檔案並新增作業,以設定伺服器端計算變數的值。 範例包括擷取資料或其他伺服器作業。

    export default function Home() {
        const timeOnServer = new Date().toLocaleTimeString('en-US');
        return(
            ...
        );
    }
    
  2. next/cache 匯入 unstable_noStore,並在 Home 元件內呼叫它,以確保會動態轉譯路由。

    import { unstable_noStore as noStore } from 'next/cache';
    
    export default function Home() {
        noStore();
    
        const timeOnServer = new Date().toLocaleTimeString('en-US');
        return(
            ...
        );
    }
    

    注意

    此範例會強制此元件的動態轉譯,以示範伺服器目前時間的伺服器轉譯。 Next.js 的應用程式路由器模型建議快取個別資料要求,以最佳化 Next.js 應用程式的效能。 深入了解 Next.js 中的資料擷取和快取

  3. 更新 app/pages.tsx 中的 Home元件,以轉譯伺服器端資料。

    import { unstable_noStore as noStore } from 'next/cache';
    
    export default function Home() {
        noStore();
    
        const timeOnServer = new Date().toLocaleTimeString('en-US');
        return(
            <main className="flex min-h-screen flex-col items-center justify-between p-24">
                <div>
                    This is a Next.js application hosted on Azure Static Web Apps with hybrid rendering. The time on the server is <strong>{timeOnServer}</strong>.
                </div>
            </main>
        );
    }
    

新增 API 路由

除了伺服器元件以外,Next.js 還提供路由處理常式,可以用來建立與 Next.js 應用程式的 API 路由。 您可以在用戶端元件中擷取這些 API。

從新增 API 路由開始。

  1. app/api/currentTime/route.tsx 建立新檔案。 此檔案會保存新 API 端點的路由處理常式。

  2. 新增處理常式函式,以從 API 傳回資料。

    import { NextResponse } from 'next/server';
    
    export const dynamic = 'force-dynamic';
    
    export async function GET() { 
        const currentTime = new Date().toLocaleTimeString('en-US');
    
        return NextResponse.json({ 
            message: `Hello from the API! The current time is ${currentTime}.`
        });
    }
    
  3. app/components/CurrentTimeFromAPI.tsx 建立新檔案。 此元件會為用戶端元件建立容器,以從瀏覽器擷取 API。

  4. 新增可擷取此檔案中 API 的用戶端元件。

    'use client';
    
    import { useEffect, useState } from 'react';
    
    export function CurrentTimeFromAPI(){
        const [apiResponse, setApiResponse] = useState('');
        const [loading, setLoading] = useState(true);
    
        useEffect(() => {
            fetch('/api/currentTime')
                .then((res) => res.json())
                .then((data) => {
                setApiResponse(data.message);
                setLoading(false);
                });
            }, 
        []);
    
        return (
            <div className='pt-4'>
                The message from the API is: <strong>{apiResponse}</strong>
            </div>
        )
    }
    

此用戶端元件會擷取具有 useEffect React 勾點的 API,以在載入完成之後轉譯元件。 'use client' 指示詞會將此元素識別為用戶端元件。 如需詳細資訊,請參閱用戶端元件

  1. 編輯 app/page.tsx 以匯入和轉譯 CurrentTimeFromAPI 用戶端元件。

    import { unstable_noStore as noStore } from 'next/cache';
    import { CurrentTimeFromAPI } from './components/CurrentTimeFromAPI';
    
    export default function Home() {
        noStore();
    
        const timeOnServer = new Date().toLocaleTimeString('en-US');
        return(
            <main className="flex min-h-screen flex-col items-center justify-between p-24">
                <div>
                    This is a Next.js application hosted on Azure Static Web Apps with hybrid rendering. The time on the server is <strong>{timeOnServer}</strong>.
                </div>
                <CurrentTimeFromAPI />
            </main>
        );
    }
    
  2. 頁面上會顯示來自 API 路由的結果。

顯示來自 API 路由輸出的螢幕擷取畫面。

設定 Next.js 的執行階段版本

某些 Next.js 版本需要特定的 Node.js 版本。 若要設定特定的 Node 版本,您可以設定 package.json 檔案的 engines 屬性來指定版本。

{
  ...
  "engines": {
    "node": "18.17.1"
  }
}

設定 Next.js 的環境變數

Next.js 會在建置時間和要求時間使用環境變數,以同時支援使用伺服器端轉譯的靜態頁面產生和動態頁面產生。 因此,請在建置和部署工作內,以及 Azure Static Web Apps 資源的環境變數中設定環境變數。

...
      - name: Build And Deploy
        id: builddeploy
        uses: Azure/static-web-apps-deploy@v1
        with:
          azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
          repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
          action: "upload"
          app_location: "/" 
          api_location: ""
          output_location: "" 
        env:
          DB_HOST: ${{ secrets.DB_HOST }}
          DB_USER: ${{ secrets.DB_USER }}
          DB_DATABASE: ${{ secrets.DB_DATABASE }}
          DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
          DB_PORT: ${{ secrets.DB_PORT }}
...

啟用獨立功能

當應用程式大小超過 250 MB 時,Next.js 輸出檔案追蹤功能可協助最佳化應用程式大小並增強效能。

輸出檔案追蹤會建立具有必要套件相依性的整個應用程式的壓縮版本。 此套件內建於名為 .next/standalone 的資料夾。 使用此套件,您的應用程式可以自行部署,而不需要 node_modules 相依性。

若要啟用 standalone 功能,請將下列屬性新增至 next.config.js

module.exports ={
    output:"standalone",
}

接下來,在 package.json 檔案中設定 build 命令,以便將靜態檔案複製到您的獨立輸出。

{
  ...
  "scripts": {
    ...
    "build": "next build && cp -r .next/static .next/standalone/.next/ && cp -r public .next/standalone/"
    ...
  }
  ...
}

設定部署的路由和中介軟體

您可以使用自訂重新導向、重寫和中介軟體來設定路由的 Next.js 專案控制代碼。 這些處理常式通常用於驗證、個人化、路由和國際化。 自訂處理會影響 Next.js 網站的預設路由,且設定必須與 Static Web Apps 上的裝載相容。

Static Web Apps 會藉由在建置時間將頁面新增至您的網站,來驗證您的 Next.js 網站已成功部署。 頁面名為 public/.swa/health.html,而 Static Web Apps 會瀏覽至 /.swa/health.html 並驗證成功的回應,以驗證網站成功啟動和部署。 中介軟體和自訂路由,其包括重新導向和改寫,可能會影響 /.swa/health.html 路徑的存取,其可能防止 Static Web Apps 的部署驗證。 若要設定中介軟體和路由以成功部署至 Static Web Apps,請遵循下列步驟:

  1. 在您的中介軟體設定中的 middleware.ts (或 .js) 檔案中排除開頭為 .swa 的路由。

    export const config = {
      matcher: [
        /*
         * Match all request paths except for the ones starting with:
         * - .swa (Azure Static Web Apps)
         */
        '/((?!.swa).*)',
      ],
    }
    
  2. next.config.js 中設定您的重新導向,以排除開頭為 .swa 的路由。

    module.exports = {
        async redirects() {
            return [
              {
                source: '/((?!.swa).*)<YOUR MATCHING RULE>',
                destination: '<YOUR REDIRECT RULE>', 
                permanent: false,
              },
            ]
        },
    };
    
  3. next.config.js 中設定您的重寫規則,以排除開頭為 .swa 的路由。

    module.exports = {
        async rewrites() {
            return {
                beforeFiles: [
                    {
                        source: '/((?!.swa).*)<YOUR MATCHING RULE>',
                        destination: '<YOUR REWRITE RULE>', 
                    }
                ]
            }
        },
    };
    

這些程式碼片段會排除開頭為 .swa 的路徑,以讓您的自訂路由或中介軟體無法處理這些要求。 這些規則可確保在部署驗證期間如預期般解析路徑。

啟用 Next.js 的記錄

遵循 Next.js 伺服器 API 疑難排解的最佳做法,將記錄新增至 API 以捕捉這些錯誤。 Azure 上的記錄會使用 Application Insights。 若要預先載入此 SDK,您必須建立自訂啟動指令碼。 若要深入了解:

清除資源

如果您不打算繼續使用此應用程式,您可以透過下列步驟刪除 Azure Static Web Apps 執行個體:

  1. 開啟 Azure 入口網站
  2. 從頂端的搜尋列搜尋 my-first-web-static-app
  3. 選取該應用程式名稱。
  4. 選取 [刪除]
  5. 選取 [是] 以確認刪除動作 (此動作可能需要幾分鐘的時間才能完成)。

下一步