I am trying to run a very simple node.js server on an Azure Web Appp to serve a single page application. The server will serve up static pages, and will always server 'index.html' for page requests as all the routing is done client side.
All works absolutely perfectly locally, but when deploying to Azure, any page requests result in a 'the resource you are looking for has been removed...', which suggests the node server isn't being hit.
I am using Koa as the server, and the server.js is here;
var Koa = require('koa');
var convert = require('koa-convert');
var helmet = require('koa-helmet');
var historyApiFallback = require('koa-connect-history-api-fallback');
var serve = require('koa-static');
var app = new Koa();
// This rewrites all routes requests to the root /index.html file
// (ignoring file requests). If you want to implement isomorphic
// rendering, you'll want to remove this middleware.
app.use(convert(historyApiFallback({
verbose: false
})));
// Serving ~/dist by default. Ideally these files should be served by
// the web server and not the app server, but this helps to demo the
// server in production.
app.use(convert(serve(__dirname)));
app.use(helmet());
var server = app.listen(3000);var Koa = require('koa');
var convert = require('koa-convert');
var helmet = require('koa-helmet');
var historyApiFallback = require('koa-connect-history-api-fallback');
var serve = require('koa-static');
var app = new Koa();
// This rewrites all routes requests to the root /index.html file
// (ignoring file requests). If you want to implement isomorphic
// rendering, you'll want to remove this middleware.
app.use(convert(historyApiFallback({
verbose: false
})));
// Serving ~/dist by default. Ideally these files should be served by
// the web server and not the app server, but this helps to demo the
// server in production.
app.use(convert(serve(__dirname)));
app.use(helmet());
var server = app.listen(3000);
I have included the package.json on the deployment as some documentation suggested that required node packages would be auto-installed (Koa etc), but it doesnt seem as though that has worked.
Any ideas?
Windows Azure Websites uses IISNode to host the Node process inside of IIS. Your Node site is actually given a Named Pipe which receives the incoming requests, not a TCP port like you would use when running locally or hosting yourself. Even if you could open a TCP port, Azure Websites are really only meant for traditional websites and don't have a way to open ports to the outside world.
So, first, you need to change the port in your code, e.g.:
var port = process.env.PORT||3000; //which you can run both on Azure or local
var server = app.listen(process.env.PORT||3000);
And in my test, there are several additional configurations we need to configure to remove errors from application to make it run on Azure Web App.
It seems it will raise the same issue with https://github.com/alexmingoia/koa-router/issues/177 directly run koa apps on Azure, so we need to configure the nodeProcessCommandLine
:
create a the a file named iisnode.yml
with the content:
nodeProcessCommandLine:"%programfiles%\nodejs\%WEBSITE_NODE_DEFAULT_VERSION%\node.exe" --harmony-generators
the setting WEBSITE_NODE_DEFAULT_VERSION is relative to the value you set in app settings in configure tab of in your site manager portal.
As a node.js application running on Azure Web Apps, needs a server.js
or app.js
file as the entrance in the root directory with a web.config
file to control the iis (it will automatically create if you deploy via git or build the app server via node.js template). E.G.
<configuration>
<system.webServer>
<handlers>
<!-- indicates that the app.js file is a node.js application to be handled by the iisnode module -->
<add name="iisnode" path="server.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<!-- 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>
<!-- Don't 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 application entry point -->
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True" />
</conditions>
<action type="Rewrite" url="server.js" />
</rule>
</rules>
</rewrite>
</system.webServer>
So you can put your SPA files in the public
folder in root directory, e.g. your SPA entrance is index.html
, when you visit <your_site_name>.azurewebsites.net/index.html
it will rewrite to "/public/index.html".
Additionally, you can leverage VSO to debug your application on Azure online, refer to Visual Studio 2015 and Microsoft Azure syncing files, Server/Local for more.
I can see duplicated code in your code above. Remove the code after var server = app.listen(3000);
then follow the steps in article https://azure.microsoft.com/en-us/documentation/articles/web-sites-nodejs-develop-deploy-mac to finish depoly your KOA to azure.