2

just a heads up: This is the first time I try to deploy a react application on a custom built windows server, but I’ve managed to do it successfully on Heroku and Linux (PM2), so I know that the application architecture is suppose to work correctly.

The scenario:

I’ve built a Windows Server 2016 / 64 bits hosting server to host multiple websites. I’ve used VPS Contabo to do so. I’ve tested all features that are suppose to work, even with other applications such as ASP.NET, PHP, SSL certificates and everything is working fine.

As for the specific node js project that I’m trying to host on this server, It consists of 2 main parts:

  • Backend in node together with a CMS, also developed in node / javascript. I created a hosting space on a subdomain for this one and it’s working perfectly, even with the Let’s Encrypt SSL certificate. In case anyone wants to access it, would be on: https://backendnode.fullstackwebdesigner.com/system

  • Frontend in react server side rendering. This is where the problem is occurring. If anyone would like to access it, here’s the link: https://fullstackwebdesigner.com/

I used basically the same technique for both of them:

  • iisnode;
  • URL rewrite extension;
  • iis node modules;
  • web.config file configuration;

The problem:

I’ve managed to get it to load as a website, just like I did with the backend, but the problem is that it seems not to load the CSS files, images and so on. So the layout doesn’t load. On the console, there’s and error message: Uncaught SyntaxError: Unexpected token '<'

The react application: As I’ve said before, it was done as a server side rendering application and bundled with webpack. So it builds the bundled files to a directory called “/build”. And in this directory, there’s a “/public” directory where all assets are in, like CSS files and images.

While developing, I would run the build on the terminal as: node build/bundle.react.js

And as strange as it may seem, when I run this on the terminal on the windows server, It works perfectly. But can only be accessed through: http://localhost:3001 It loads everything that’s suppose to load.

Here’s a simplified representation of the file structure:

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

Here’s also the web.config file I’m using on the website hosting space for the react build:

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

Anyone has any idea of what could be missing or going on, as there hasn’t many references on hosting server side rendering on windows server on the web? Maybe an extra configuration on IIS, web.config or on the website hosting space?

1

Got it to work! The following link helped me make the final adjustments, along with the test I did: https://www.thecodehubs.com/how-to-deploy-ssr-angular-universal-to-iis/ Summing it up, turns out I had to copy the server bundle to the root directory. And change the web.config file to call the root file. Here’s how the web.config file ended up, along with some more configurations that I found interesting in the link I posted (didn’t test yet without the extra configuration):

<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" />
            </hiddenSegments>
          </requestFiltering>
        </security>
    </system.webServer>
    <system.web>
        <compilation defaultLanguage="js" />
    </system.web>
</configuration>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.