﻿# 如何將 Next.js 製作的網站以 Node.js 的方式部署到 Azure Web App

要將 [Node.js](https://nodejs.org/) 網站部署到 Azure Web App (Windows) 其實有點竅門，一般不熟悉 Windows / IIS 的開發人員要想把手邊的 Node.js 部署到 Azure Web App 通常都會卡關卡好久。這篇文章我就來說說我是如何將我最近翻譯的[提示工程指南](https://www.promptingguide.ai/zh)網站部署到 Azure Web App 的，而這是一個用 [Next.js](https://nextjs.org) 開發的網站！

![將 Next.js 製作的網站以 Node.js 的方式部署到 Azure Web App](https://stwillblogassets.blob.core.windows.net/files/images/external/user-images.githubusercontent.com/2bd62ccfe5033c22c8f5-227722119-1bc64fa2-847e-40a6-9fa9-19ba88cc6fda.jpg)

以下有幾點注意事項：

1.  網站根目錄要有個 `package.json` 檔案，而且要寫好 `npm start` 可以啟動網站的腳本！
    
    以我的網站為例，我的設定值如下：
    
    ```json
    {
      ...
      "scripts": {
        "dev": "next dev",
        "build": "next build",
        "start": "next start"
      },
      ...
    }
    ```
    
2.  你必須安裝 `express` 套件
    
    ```bash
    npm install express
    ```
    
3.  你必須新增一個 `server.js` 檔案，並透過 `express` 轉送 HTTP 要求給 [Next.js](https://nextjs.org)
    
    這裡的另一個重點是 `process.env.PORT` 環境變數，因為要在 Azure Web App 跑 Node.js 必須是動態決定的 Port 埠號，並且透過 `PORT` 環境變數傳入。這一點也是初學者經常卡關的地方！
    
    ```javascript
    const express = require('express')
    const next = require('next')
    
    const dev = process.env.NODE_ENV !== 'production'
    const app = next({ dev })
    const handle = app.getRequestHandler()
    
    // Your app will get the Azure port from the process.enc.PORT
    const port = process.env.PORT || 3000;
    
    app
      .prepare()
      .then(() => {
        const server = express()
    
        server.get('*', (req, res) => {
          return handle(req, res)
        })
    
        server.listen(port, err => {
          if (err) throw err
          console.log('> Ready on http://localhost:3000')
        })
      })
      .catch(ex => {
        console.error(ex.stack)
        process.exit(1)
      })
    ```
    
4.  你必須新增一個 `web.config` 檔案
    
    最後這個步驟也是最關鍵的，因為大多數 Node.js 開發者並不熟悉 `web.config` 這個 IIS 設定檔，所以也是另一個卡關的環節。
    
    這裡不用想太多，你不太需要知道 `iisnode` 模組要怎麼用，把以下內容完整複製貼上即可：
    
    ```xml
    <?xml version="1.0" encoding="utf-8"?>
    <!--
        This configuration file is required if iisnode is used to run node processes behind
        IIS or IIS Express.  For more information, visit:
    
        <https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config>
    -->
    
    <configuration>
      <system.webServer>
        <!-- Visit <http://blogs.msdn.com/b/windowsazure/archive/2013/11/14/introduction-to-websockets-on-windows-azure-web-sites.aspx> for more information on WebSocket support -->
        <webSocket enabled="false" />
        <handlers>
          <!-- Indicates that the server.js file is a node.js site to be handled by the iisnode module -->
          <add name="iisnode" path="server.js" verb="*" modules="iisnode"/>
        </handlers>
        <rewrite>
          <rules>
            <!-- Do not interfere with requests for node-inspector debugging -->
            <rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
              <match url="^server.js\\/debug[\\/]?" />
            </rule>
    
            <!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
            <rule name="StaticContent">
              <action type="Rewrite" url="public{REQUEST_URI}"/>
            </rule>
    
            <!-- All other URLs are mapped to the node.js site entry point -->
            <rule name="DynamicContent">
              <conditions>
                <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
              </conditions>
              <action type="Rewrite" url="server.js"/>
            </rule>
          </rules>
        </rewrite>
    
        <!-- 'bin' directory has no special meaning in node.js and apps can be placed in it -->
        <security>
          <requestFiltering>
            <hiddenSegments>
              <remove segment="bin"/>
            </hiddenSegments>
          </requestFiltering>
        </security>
    
        <!-- Make sure error responses are left untouched -->
        <httpErrors existingResponse="PassThrough" />
    
        <!--
          You can control how Node is hosted within IIS using the following options:
            * watchedFiles: semi-colon separated list of files that will be watched for changes to restart the server
            * node_env: will be propagated to node as NODE_ENV environment variable
            * debuggingEnabled - controls whether the built-in debugger is enabled
    
          See <https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config> for a full list of options
        -->
        <iisnode watchedFiles="web.config;*.js"/>
      </system.webServer>
    </configuration>
    ```
    

如此一來就部署成功啦！👍

### 總結

總結的來說，要在 Azure Web App (Windows) 部署 Node.js 應用程式，大概有以下幾個要點：

1.  一定要有個 `web.config` 設定檔，設定好 `iisnode` 模組與 [URL Rewrite](https://www.iis.net/downloads/microsoft/url-rewrite) 才能跑。
    
2.  網站根目錄要有個 `package.json` 檔案，而且要寫好 `npm start` 可以啟動網站的腳本！
    
3.  需要一個啟動程式 (`server.js`)，並且要指定 `process.env.PORT` 為主要 LISTEN 的埠號(Port)。
    
    如果像是 Next.js 這種找不到 `server.js` 啟動程式的架構，就需要自定義一個 `server.js` 啟動程式，可選用 express 做入口，將要求轉送 next 來處理。
    

### 相關連結

-   [Deployment | Next.js](https://nextjs.org/docs/deployment)
-   [Deploy Next.js websites on Azure Static Web Apps](https://learn.microsoft.com/en-us/azure/static-web-apps/nextjs?WT.mc_id=DT-MVP-4015686)
-   [快速入門：建立 Node.js Web 應用程式 - Azure App Service | Microsoft Learn](https://learn.microsoft.com/zh-tw/azure/app-service/quickstart-nodejs?tabs=windows&WT.mc_id=DT-MVP-4015686&pivots=development-environment-vscode)
-   [設定 Node.js 應用程式 - Azure App Service | Microsoft Learn](https://learn.microsoft.com/zh-tw/azure/app-service/configure-language-nodejs?WT.mc_id=DT-MVP-4015686&pivots=platform-windows)
-   [Node.js best practices and troubleshooting - Azure App Service | Microsoft Learn](https://learn.microsoft.com/en-us/azure/app-service/app-service-web-nodejs-best-practices-and-troubleshoot-guide?WT.mc_id=DT-MVP-4015686)
    -   中文翻譯: [Node.js 最佳做法和疑難排解 - Azure App Service | Microsoft Learn](https://learn.microsoft.com/zh-tw/azure/app-service/app-service-web-nodejs-best-practices-and-troubleshoot-guide?WT.mc_id=DT-MVP-4015686)
-   [Deploying Next.JS App on Azure App Service](https://parveensingh.com/next-js-deployment-on-azure-app-service/)
-   [reactjs - Cannot deploy Nextjs application on app service using Azure Pipleline - Stack Overflow](https://stackoverflow.com/a/72642717)
-   [Running Next.js on Azure App Services | by David Fekke | CodeX | Medium](https://medium.com/codex/running-next-js-on-azure-app-services-84f707af761d)
