Angular 2 : Giving Your CLI a Server
...be sure to read Angular 2:Re-Quickstart with the CLI
Although the CLI includes a number of great features, the deployment of the application is a story or issue that is still under discussion (Production deploy #326).
What is the right server, what are the features etc.
A simple static server for Angular applications should be able to handle a few things:
- static files - like that pesky fav.ico, images, css, and javascript files
- deep links - routing to specific portion of our SPA
- maybe something simple like compression
In this case, node.js using Express fits the bill. Let's see how to add it to the quickstart generated in the previous post.
First, grab the index.js and package.json files from the gist https://gist.github.com/spboyer/1aa7ac47bf0631a30d9eafd7b1af1186
var express = require('express'),
path = require('path'),
fs = require('fs');
var app = express();
var staticRoot = __dirname + '/';
app.set('port', (process.env.PORT || 3000));
app.use(express.static(staticRoot));
app.use(function(req, res, next){
// if the request is not html then move along
var accept = req.accepts('html', 'json', 'xml');
if(accept !== 'html'){
return next();
}
// if the request has a '.' assume that it's for a file, move along
var ext = path.extname(req.path);
if (ext !== ''){
return next();
}
fs.createReadStream(staticRoot + 'index.html').pipe(res);
});
app.listen(app.get('port'), function() {
console.log('app running on port', app.get('port'));
});
and create them (server.js, project.json) in a folder in the root of the project called node-server
.
Next, we will need to add a few npm scripts to the package.json for a custom build script.
Add the following commands:
"build:nodeserver": "ng build && cp nodeserver\/* dist",
"build:nodeserver-prod": "ng build -prod && cp nodeserver\/* dist",
"serve-build" : "npm run build:nodeserver && cd dist && node index.js",
"serve-build-prod": "npm run build:nodeserver-prod && cd dist && node index.js"
The first command runs the normal ng build
command which builds the application and places the assets into the /dist directory followed by a copy command to copy the /node-server files to the /dist folder.
The second command does the same, but passing the -prod
option tells the CLI to bundle the application assets.
Execute the command using npm run build:nodeserver
or npm run build:nodeserver-prod
Finally the last two commands run the application using the node server from the local machine in either dev or production mode. Browse to http://localhost:3000 to see the app running from node.js
Execute the command using npm run serve-build
or npm run serve-build-prod
Bonus: Adding to CI Process
In the Angular 2 : Continuous Integration to Azure using Codeship and the Angular CLI post, it showed how to use the CLI and Codeship to push an app to Azure.
In that scenario, the application is being served by IIS; a perfectly and very performant static server. However, the deep link issue is still an issue. With adding the node.js/express server above and adjusting the "Testing Pipelines" script from
#serve the application adding '&' to run command in background
ng serve &
#start end to end tests using protractor
ng e2e
#if all of the tests pass, then build the production assets
ng build -prod
to
#serve the application adding '&' to run command in background
ng serve &
#start end to end tests using protractor
ng e2e
#if all of the tests pass, then build the production assets
npm run build:nodeserver-prod
It would include the node server in the /dist folder when pushing to Azure. Then, Kudu (Azure's deployment engine), would see the package.json file in the /dist folder and consequently run npm install
completing the node application install and thus running a more complete server.
Related Github repo: http://github.com/spboyer/quickstart-ng-cli