Skip to content
Node.js server side library for pre-rendering complex AngularJS app. Supports caching and URL rules.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
bin - Added preboot support Jan 1, 2017
deb/original - many CORS issues fixed Oct 19, 2016
dist - Fix the serverConfig variable bug Feb 11, 2017
old/screenshots renaming wip Dec 28, 2016
src Fixes Object.assign issue Feb 11, 2017
test-server/server - Added preboot support Jan 1, 2017
test Test rewritten Dec 31, 2016
.babelrc - Another rewrite, using slimer Oct 10, 2016
.bowerrc - Added the gh-page link Sep 21, 2016
.gitignore Sometimes, I am so dumb I forget to include the actual compiled libra… Feb 11, 2017
.travis.yml - Fix the serverConfig variable bug Feb 11, 2017
LICENSE readme typos fixes Jan 1, 2017 better readme Dec 29, 2016
bower.json - Fix the serverConfig variable bug Feb 11, 2017 - many CORS issues fixed Oct 19, 2016
diagram.txt - many CORS issues fixed Oct 19, 2016 better readme Dec 29, 2016
package.json - Fix the serverConfig variable bug Feb 11, 2017
tsconfig.json - Moved the clien tinto a separate project Dec 31, 2016
typings.json v1.0.0-2 Dec 27, 2016
webpack.config.js - Moved the clien tinto a separate project Dec 31, 2016


This is a server side rendering engine for Angular 1. For Angular2+, you may look at Angular universal,

Build Status


A port of this server to Angular2 is not on the roadmap - but it is technically possible to adapt ng1-server-bower for angular2+.

Angular.js is a super heroic framework originally designed for web apps development. It usage has quickly expanded for hybrid mobile application development, with one mojo: one language to rule it all.

The only missing piece is server-side rendering, which this package aims to fix.

What does server side rendering means for angular?

  • You don't have to modify your existing Angular.js code base.
  • You can have big SEO benefits
  • You get support for REST caching out of the box
  • Your website will behave as a web application - which means a much richer UX.
  • You get huge performances benefits by server side caching REST API and templateCache and replay them in your client instantly on page load
  • You can start developing your website with Angular, server side render it, and later port it into a mobile app with cordova

##Comparing server pre-rendering with no pre-rendering

MEAN.js HTML with Angular.js MEAN.js HTML with Angular.js

MEAN.js HTML with Angular.js-server MEAN.js HTML with Angular.js-server

Getting started


First install ng1-server globally, firefox and xvfb

# Dependencies
sudo apt-get install firefox xvfb git

npm install -g ng1-server

Then install the angular client side ng-server module:

bower install --save ng1-server

You will also need to have a Redis server available.


Your angular app must use html5mode. The reason behind this requirement is that browsers don't send the hashbang fragment to the server.

Angular.js 1.5.x

This has been written with 1.5.x in mind - but it should work with 1.3+ .

Client configuration

Include the server module into your web-app.


You will then have to define a global serverConfig variable for the client app.

var serverConfig = {
    clientTimeoutValue: number,
    debug: boolean,
    httpCache: boolean,
    restCache: boolean,    
    restServerURL: string

clientTimeoutValue default = 200

You shouldn't have to change/set this setting. It is used by the client to trigger the IDLE status of the app. Once a potential IDLE status is detected, it will check again in 200ms if the app status has changed since then. If no, then this is an IDLE.

debug default = false

Turns the $ on the client.

httpCache default = false

After the client replays all the $http calls, set $http.cache to this value.

restCache default = false

Enables the REST caching functionality. Every $http call will be going trough the restServerURL.

restServerURL default = null

If restCacheEnabled, this setting is required. The restServerURL will proxy all $http request, and will cache them according to the slimerRestCacheRules.yml rules.

ng-server configuration

Create a folder configYaml inside your webapp folder, and copy paste the content of bin/configYaml inside it.

Modify the config files at your wish, then start the server passing the absolute path to your configYaml folder:

ng1-server PATH-TO-configYaml


domain: 'http://localhost:3000'
timeout: 10
preboot: false
logBasePath: '/logs'
 enabled: true
 host: ''
 port: 12203
   protocol: 'http://'
   host: ''
   port: 8881
   protocol: 'http://'
   host: ''
   port: 8882
   protocol: 'http://'
   host: ''
   port: 8883
 host: ''
 port: 6379
 socket_keepalive: true


Your webapp domain name (including the port)


Number in seconds after the server rendering will be considered as timed out.


Enables preboot support


Path where all server side log file will be stored. It will attempt to create them under / first. If failed, it will use the relative path from where the server is launched.


Turns Graylog logging on.


Defines all server addresses

ng1-server launches all 3 servers on different ports, make sure these are available.


Information about your redis server.


Tells the server which URL it should pre-render. Those not pre-rendered will return the original HTML.

strategy is always or never rules[] contains a list of Regexes. If strategy is always, then every URL matching this list will be pre-rendered. Otherwise they will be ignored.

Example 1: pre-render every URLs.

strategy: 'always'
rules: []

Example 2: pre-render only URLS ending with .html.

strategy: 'always'
    - /.*\.html$/   

Example 3: pre-render everything execpt URLS containing user.

strategy: 'never'
    - /user/   


Now the URL is pre-rendered, should the server cache this HTML for next time?


Configures what dependencies / REST url will be cached.

ex1: Scripts dependencies, want to cache all calls to angular-ui ? angular-material? your sources? This is recommended because this will greatly improves the pre-rendering speed.

ex2: Some $http rest calls are known to be static? Some other changes once in a while? You can cache them too !

Both serverCacheRules.yml and slimerRestCacheRules.yml files format specification follows redis-url-cache config file format.

How does it works?

It is composed by 5 main components,

###The Client

By design, it can be platform independent, language independent. This is a simple websocket client that queries the rendering server (Bridge) for an url or an url+html. It gets notified in real time by the bridge about the status of the query.

###The Bridge

The Bridge has two socket servers listening on two different ports. First port is dedicated for external communications with the client. The second port is dedicated to internal communications with the Angular client module (ng1-server-bower).

  • Listen and updates the the client in real time as soon something new happens( queues, starting, finished, error).
  • Spawns and manage the internal pool of slimer.js instances.
  • Once the web-app launches inside slimer, listen socket requests from the ng1-server client module about logging and application state (error | idle)

###The slimer.JS instances

Each pre-rendering is made via slimer.js which is similar to phantom.js. It simulates a real web-browser environment, and execute the URL/HTML.

  • Communicates with it parent's process trough websocket, sending runtimes informations
  • Intercept every network communication ( <script> loading, '$http' calls, and forward them to the cache web server.
  • Makes sure no zombie are left behind
  • Handles runtimes error

###The ng1-Server-bower client module

This module is included inside the angular web-app and modifies several providers to adapt with the server side environment.

When running on server:

  • Forwards all $log calls to the bridge
  • When detecting the IDLE event, it sends the rendered HTML to the bridge AND exports the $cacheFactory's content to the bridge

When running on the client's browser:

  • Replays the $cacheFactory content for faster client side rendering
  • If enabled, forward all $http calls to the cache web server

###A Cache Web Server

The cache server is a custom proxy/cdn that will cache urls depending on regex rules you specify in the config file slimerRestCacheRules.yaml It is used by the slimmer.js instances and the ng1-server-bower angualr module


This is a beta, and it is still WIP. What need to be done before reaching stable release is :

  • All cases for e2e testing have to be implemented Documented here
  • Packaging the server into .deb, .rpm, mac os and windows .exe binaries ( possible with nexe )


Simply run npm run test or check the travis output

The web app used to run the tests can be found here. This app needs to get updated to support testing of

  • cookies
  • authentication
  • preboot

Main dependencies

  • Bunyan to log server related metrics and web app behavior. It also integrates with Graylog
  • Ng1-server client library to link this all together.
  • Preboot to manage the transition of state (i.e. events, focus, data) from a server-generated web view to a client-generated web view.
  • Redis Url Cache to handle the url caching and
  • Slimer.JS to execute the angular app in a browser like environment on the server,
  • Socket-io to establish communication between the application modules.


So far, only one client ng1-server-node-client is implemented.

Install it by running npm install --save ng1-server-node-client inside your web server project.

The client connects to the ngServer port specified in the config.

var Client = require('ng1-server-node-client`);

# is the Bridge_external url defined inside your serverConfig.yaml

var client = new Client('');

client.renderURL(url, function( response ) {

client.renderHTML(url, html, function( response ) {

For more information, check ng1-server-node-client 's README.


File logging

ngServer uses Bunyan to log useful information and any errors raised.

The following log files are created, depending on the value of serverConfig.logBasePath:

cd $logBasePath

# Server logs

# Web application logs triggered with angular's $log


You can forward all these logs to a GrayLog server by changing the config serverConfig.gelf. Note that the input must be UDP.


Contributors are very much welcomed. I currently work full time, and my free time to help with this project can sometimes be very limited.

Also don't hesitate to file issues.

You can’t perform that action at this time.