0

While my app runs fine locally, I'm having a difficult time deploying it to an Azure Web App.

The structure of the application is as follows:

  • ./index.html
  • ./app.js - main node.js code, including Express middleware
  • ./*.js - supporting myapp's node.js code
  • ./assets/angular - Angular.js v1.2.x
  • ./assets/bootstrap
  • ./assets/css
  • ./assets/img
  • ./views - views for the application
  • state.js routes to /myapp/* (e.g., /myapp/home, /myapp/login).
  • all Express API calls are to /api/* (e.g., /api/version)

After piecing together tidbits from other sources, my best guess for a web.config is as follows:

<handlers>
  <!-- Indicates that the app.js file is a node.js site to be handled by the iisnode module -->
  <add name="iisnode" path="app.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="^app.js\/debug[\/]?" />
    </rule>

    <rule name="Static files" stopProcessing="true">
      <match url=".*" />
      <conditions logicalGrouping="MatchAll">
        <!-- Core application files -->
        <add input="{REQUEST_URI}" pattern="assets/" ignoreCase="true" />
        <add input="{REQUEST_URI}" pattern="views/" ignoreCase="true" />
      </conditions>
      <action type="Rewrite" url="{REQUEST_URI}" />
    </rule>

    <rule name="Express.js API">
      <match url="api/*" />
      <action type="Rewrite" url="app.js"/>
    </rule>

    <rule name="Angular">
      <match url=".*" />
      <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
      </conditions>
      <action type="Rewrite" url="index.html" />
    </rule>        
  </rules>
</rewrite>

Unfortunately, after publishing to Azure, while most of the assets/ and index.html file are loaded (as viewed in browser debug window), I get a "Failed to load resource: the server responded with a status of 500 (Internal Server Error)" on the /assets/angular/app.js.

What could be causing this issue? Furthermore, is there a standard for deploying MEAN apps on Azure? Is there a standard web.config for this type of MEAN app?

HiDefLoLife
  • 555
  • 1
  • 8
  • 28
  • See if [these steps](https://github.com/projectkudu/kudu/wiki/Troubleshooting-Node-errors) help diagnose the problem. – David Ebbo Sep 14 '17 at 19:03
  • It says "Application has thrown an uncaught exception and is terminated: ReferenceError: myapp is not defined at Object. (D:\home\site\wwwroot\assets\angular\state.js:2:1). I'm guessing that either: (1) assets/angular/app.js, which defines the app wasn't run (2) index.html's line wasn't understood (which I doubt), or (3) angular itself, at assets/angular/angularjs/ didn't run – HiDefLoLife Sep 14 '17 at 20:09

1 Answers1

0

The trick for supporting MEAN applications within Azure came down to a few things:

  • Rewriting the express.js middleware requests to server.js
  • Rewriting the angular.js URI requests to index.html
  • Rewriting all static file requests - for example, Angular assets, CSS, Images, etc. - as is/directly to the requested URI
  • Importantly, so that Azure can handle your requests properly through a defined port, opening up the express.js server at process.env.PORT

Within server.js:

    // Within server.js - make sure we're listening on the proper port
    server.listen(process.env.PORT, function () {
        logger.info('Web server listening on port ' + process.env.PORT)
    });

Then for web.config:

<handlers>
   <!-- Indicates that the app.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>

  <!-- For static files, redirect to the URI -->
  <rule name="Static files" stopProcessing="true">
    <match url=".*" />
    <conditions logicalGrouping="MatchAll">
      <!-- Any directory/file in the assets/ or views/ directory -->
      <add input="{REQUEST_URI}" pattern="assets\/" ignoreCase="true" />
      <add input="{REQUEST_URI}" pattern="views\/" ignoreCase="true" />
    </conditions>
    <action type="Rewrite" url="{REQUEST_URI}"/>
  </rule>

  <!-- For Express.js middleware API, if using api/ prefix, then use server.js -->
  <rule name="Express.js URIs">
    <match url="api/*" />
    <action type="Rewrite" url="server.js" />
  </rule>

  <!-- For Angular.js URIs, rewrite to the index.html file -->
  <rule name="Angular">
    <match url=".*" />
    <conditions logicalGrouping="MatchAll">
      <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
      <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
    </conditions>
    <action type="Rewrite" url="index.html" />
  </rule>  

</rules>
</rewrite>

And for anyone that gets stumped with a similar issue, may I recommend:

  • Your browser's developer tools - e.g., for Chrome - I was able to use console.log's within my Angular application to determine that my express api was called but not returned
  • Postman (to see results of express.js requests), allowed me to view the URI request error codes and determine that the port may be an issue
  • Azure's Kudu toolset, which allows access to Application log files, it helped me determine whether it was my application or URI requests to the working application causing the problem
HiDefLoLife
  • 555
  • 1
  • 8
  • 28