如何在 Windows Server 2016/IIS 上部署服务器端渲染 (SSR) React 应用程序(由 Webpack 捆绑)

如何在 Windows Server 2016/IIS 上部署服务器端渲染 (SSR) React 应用程序(由 Webpack 捆绑)

提醒一下:这是我第一次尝试在定制的 Windows 服务器上部署 React 应用程序,但我已经成功地在 Heroku 和 Linux(PM2)上完成了此操作,所以我知道应用程序架构应该可以正常工作。

场景:

我构建了一个 Windows Server 2016/64 位托管服务器来托管多个网站。我使用 VPS Contabo 来实现这一点。我测试了所有应该可以运行的功能,甚至测试了其他应用程序(例如 ASP.NET、PHP、SSL 证书),一切运行正常。

至于我尝试在此服务器上托管的特定 Node js 项目,它由两个主要部分组成:

  • 节点中的后端与 CMS 一起,也是在节点/javascript 中开发的。

我为此在子域上创建了一个托管空间,它运行良好,即使使用 Let's Encrypt SSL 证书也是如此。如果有人想访问它,请登录: https://backendnode.fullstackwebdesigner.com/system

  • 前端在 React 服务器端渲染中。

问题就出在这里。如果有人想访问它,以下是链接: https://fullstackwebdesigner.com/

我对它们两个基本上使用了相同的技术:

  • iis节点;
  • URL 重写扩展;
  • iis 节点模块;
  • web.config文件的配置;

问题:

我设法让它作为网站加载,就像我对后端所做的那样,但问题是它似乎没有加载 CSS 文件、图像等。因此布局没有加载。在控制台上,有一条错误消息: Uncaught SyntaxError: Unexpected token '<'

React 应用程序:正如我之前所说,它是作为服务器端渲染应用程序完成的,并使用 webpack 进行捆绑。因此,它将捆绑文件构建到名为“/build”的目录中。此目录中有一个“/public”目录,其中包含所有资产,如 CSS 文件和图像。

在开发过程中,我会在终端上运行构建:node build/bundle.react.js

尽管看起来很奇怪,但当我在 Windows 服务器上的终端上运行它时,它运行正常。但只能通过以下方式访问:http://localhost:3001 它会加载所有应该加载的内容。

以下是文件结构的简化表示:

- /build/
--bundle.react.js
--/build/public/
---/files-layout/
---/fonts/
---bundle.react.client.js

这也是我在网站托管空间上用于 React 构建的 web.config 文件:

<configuration>
    <system.webServer>
        <iisnode nodeProcessCommandLine="C:\Program Files\nodejs\node.exe" />
        
        <handlers>
            <add name="iisnode" path="/build/bundle.react.js" verb="*" modules="iisnode" />
        </handlers>

        <rewrite>
            <rules>
                <!-- Redirect to HTTPS (alternative). -->
                <rule name="Redirect to HTTPS / SSL" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions>
                        <add input="{HTTPS}" pattern="off" ignoreCase="true" />
                    </conditions>
                    <action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
                </rule>

                <!-- Don't interfere with requests for logs. -->
                <rule name="LogFile" patternSyntax="ECMAScript" stopProcessing="true">
                    <match url="^[a-zA-Z0-9_\-]+\.js\.logs\/\d+\.txt$" />
                </rule> 
                <!-- Node. -->
                <rule name="sendToNode">
                    <match url="(.*)" />
                    <conditions>
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="/build/bundle.react.js" />          
                </rule>
            </rules>    
        </rewrite> 
        <defaultDocument>
            <files>
                <clear />
                <add value="/build/bundle.react.js" />
            </files>
        </defaultDocument>
        <security>
            <requestFiltering>
                <hiddenSegments>
                    <add segment="node_modules" />
                </hiddenSegments>
            </requestFiltering>
        </security>
    </system.webServer>
    <system.web>
        <compilation defaultLanguage="js" />
    </system.web>
</configuration>

有谁知道可能缺少什么或发生了什么,因为网络上没有太多关于在 Windows Server 上托管服务器端渲染的参考资料?也许是 IIS、web.config 或网站托管空间上的额外配置?

编辑:

我刚刚做了一个有趣的测试:在我的本地开发计算机上,当我通过终端运行时:

node bundle.react.js

从 /build 文件夹内部,我得到了与在线发生的问题相同的结果(没有布局、样式、图像等)。

但是当我运行终端时:

node build/bundle.react.js

从 /build 文件夹外部(从基础目录),它可以完美加载。

还有更多。基础目录的组织方式如下:

…(some folders)
- /build/
--bundle.react.js
--/build/public/
---/files-layout/
---/fonts/
---bundle.react.client.js
-node_modules
…(some root files, like webpack and so on)

我猜测由于我编写 web.config 文件的方式,引用 /node_modules 文件夹时存在某种问题,但我不知道应该如何引用它。

答案1

成功了!以下链接帮助我进行了最后的调整以及测试: https://www.thecodehubs.com/how-to-deploy-ssr-angular-universal-to-iis/

总结一下,原来我必须将服务器包复制到根目录。并更改 web.config 文件以调用根文件。以下是 web.config 文件的最终结果,以及我在发布的链接中发现的一些有趣的配置(没有额外配置,尚未测试):

<configuration>
    <system.webServer>
        <iisnode nodeProcessCommandLine="C:\Program Files\nodejs\node.exe" />
        
        <handlers>
            <add name="iisnode" path="bundle.react.js" verb="*" modules="iisnode" />
        </handlers>

        <rewrite>
            <rules>
                <!-- Redirect to HTTPS. -->
                <rule name="Redirect to HTTPS / SSL" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions>
                        <add input="{HTTPS}" pattern="off" ignoreCase="true" />
                    </conditions>
                    <action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
                </rule>

                <!-- Don't interfere with requests for logs. -->
                <rule name="LogFile" patternSyntax="ECMAScript" stopProcessing="true">
                    <match url="^[a-zA-Z0-9_\-]+\.js\.logs\/\d+\.txt$" />
                </rule>
                
                <!-- Node. -->
                <rule name="sendToNode">
                    <match url="(.*)" />
                    <conditions>
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="bundle.react.js" />
                </rule>
                
                <rule name="StaticContent" stopProcessing="true">
                  <match url="([\S]+[.](jpg|jpeg|gif|css|png|js|ts|cscc|less|ico|html|map|svg))" />
                  <action type="None" />
                </rule>
            </rules>
        </rewrite> 
        
        <staticContent>
            <clientCache cacheControlMode="UseMaxAge" />
            <remove fileExtension=".svg" />
            <remove fileExtension=".eot" />
            <remove fileExtension=".ttf" />
            <remove fileExtension=".woff" />
            <remove fileExtension=".woff2" />
            <remove fileExtension=".otf" />
            <mimeMap fileExtension=".ttf" mimeType="application/octet-stream" />
            <mimeMap fileExtension=".svg" mimeType="image/svg+xml"  />
            <mimeMap fileExtension=".eot" mimeType="application/vnd.ms-fontobject" />
            <mimeMap fileExtension=".woff" mimeType="application/x-woff" />
            <mimeMap fileExtension=".woff2" mimeType="application/x-woff" />
            <mimeMap fileExtension=".otf" mimeType="application/otf" />
        </staticContent>
        
        
        <defaultDocument>
            <files>
                <clear />
                <add value="bundle.react.js" />
            </files>
        </defaultDocument>

        <security>
          <requestFiltering>
            <hiddenSegments>
              <add segment="node_modules" />
              <!--add segment="iisnode" /-->
            </hiddenSegments>
          </requestFiltering>
        </security>
    </system.webServer>
    <system.web>
        <compilation defaultLanguage="js" />
    </system.web>
</configuration>

相关内容