【问题标题】:How to deploy a NextJs SSR React app on Azure如何在 Azure 上部署 NextJs SSR React 应用程序
【发布时间】:2021-05-04 12:45:43
【问题描述】:

我一直在尝试在 Azure 上部署我使用 NextJS 构建的服务器端渲染反应应用程序。我设置了 Azure 管道并成功发布,但运行它后,当我转到 azure 网站 URL 时,应用程序似乎没有加载。构建文件内容不同于客户端呈现的应用程序。请分享有关部署 SSR React 应用程序(在 Azure 上)的资源或说明。

我使用this resource 设置了管道,我没有遇到任何错误,但 URL 仍然没有加载应用程序。

【问题讨论】:

  • 你可以看看这个视频:youtube.com/watch?v=Ny5vJRfQito&feature=youtu.be
  • @James Doris 的回答有帮助吗?如果是这样,您可以Accept it as an Answer,它可以帮助遇到相同问题的其他社区成员,谢谢。
  • @EdwardHan-MSFT 是的,我现在一切都好。答案有效
  • @EdwardHan-MSFT 这可行,但该应用程序的生产速度非常慢。加载大约需要 6-10 分钟,从一页移动到另一页平均需要 6 秒。请分享一个可能的修复方法。

标签: reactjs azure-web-app-service next.js azure-pipelines server-side-rendering


【解决方案1】:

正如@James 在Doris's answer 的评论中所提到的,在 Next.js 应用程序中使用自定义 server.js 会使其生产速度变慢,因为这些路由不是预先构建的。 Using next build followed by next start would solve this issue。但是为了让您能够做到这一点,您不应该拥有server.js

根据Microsoft documentation 在 Azure Linux Web 应用上部署 Node JS / Next JS 应用程序,推荐的方法是使用PM2 而不是使用npm start (or) node server.js

所以你don't need server.js or web.config。您需要做的就是拥有一个名为ecosystem.config.js 的文件,其内容如下

module.exports = {
  apps: [
    {
      name: "my-nextJs-site",
      script: "./node_modules/next/dist/bin/next",
      args: "start -p " + (process.env.PORT || 3000),
      watch: false,
      autorestart: true,
    },
  ],
};

让你的 Azure 应用程序的启动命令是这样的

pm2 --no-daemon start /home/site/wwwroot/ecosystem.config.js

您的 package.json 脚本没有变化

"scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",

Azure Windows 应用服务

pm2 在 Azure Windows 服务中不可用 - it uses IIS Server。查看following answer 及其相关问题。

其他有用的资源:

【讨论】:

    【解决方案2】:

    您需要两个文件:server.jsweb.config,并修改 package.json 如下所示。我已经回答了一步一步部署 nextjs 应用的问题,你可以看看this

    package.json 修改。

    "scripts": {
        "dev": "node server.js",
        "build": "next build",
        "start": "node server.js"
    

    server.js(使用以下代码创建此文件:)

    const { createServer } = require('http')
    const next = require('next')
    
    const port = parseInt(process.env.PORT, 10) || 3000
    const dev = process.env.NODE_ENV !== 'production'
    const app = next({ dev })
    const handle = app.getRequestHandler()
    
    app.prepare().then(() => {
      createServer((req, res) => {
        const parsedUrl = new URL(req.url, 'http://w.w')
        const { pathname, query } = parsedUrl
    
        if (pathname === '/a') {
          app.render(req, res, '/a', query)
        } else if (pathname === '/b') {
          app.render(req, res, '/b', query)
        } else {
          handle(req, res, parsedUrl)
        }
      }).listen(port, (err) => {
        if (err) throw err
        console.log(`> Ready on http://localhost:${port}`)
      })
    })
    

    web.config(使用以下代码创建此文件:)

    <?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> 
    

    【讨论】:

    • 这可行,但该应用程序的生产速度非常慢。加载大约需要 6-10 分钟,从一页移动到另一页平均需要 6 秒。请分享一个可能的修复方法。
    猜你喜欢
    • 2022-06-10
    • 2022-12-01
    • 1970-01-01
    • 2020-08-09
    • 2020-09-02
    • 1970-01-01
    • 2020-04-15
    • 2020-05-17
    • 1970-01-01
    相关资源
    最近更新 更多