提醒一下:这是我第一次尝试在定制的 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>