sails js production mode

Preparing your Sails JS application for production

So, you’ve built your application using Sails JS and you are ready to throw it into the world. What are the steps to prepare it for production? In this tutorial I will show you a couple of things you need to do in order to prepare your Sails JS application for production.

The Sails JS website dedicates a page on Sails JS application deployment. If you are an impatient programmer like myself you will probably scan that page and get bored quickly. Let’s see in practice how to go about launching our Sails JS app in production.

Launch your Sails JS app in development mode on the production server

You probably already did that  when developing the app, but now after copying the app to the production server it’s probably a good idea to start it in development mode once, just to see if it still works. Troubleshoot any problems related to node modules, database connection, etc.

To start the app in development mode go to the app folder and run:

sails lift

If it all works, go to the next stage.

Try launching your Sails JS application in production mode

You are now confident that it will work fine in production mode since it works like a charm in development mode. Run the following:

node app.js --prod

This tells the app that it should run in production mode. If you are lucky everything works as expected and you are fine. In this case you can skip a couple of the next steps. But, most probably you will get errors. Why? Because production mode while more appropriate for, well, production, will involve a couple of things like CSS and JS minification for example which might have unexpected results.

Let’s see a couple of challenges I’ve ran into when switching to production and their solution.

How do I change the port on which Sails JS is running?

This is an important configuration item since you will have to know how to set the port on which people will access your app. This is usually port 80 or 443 (in case you are using SSL), but often times you want it something other than that since you might be using a front end server like NGINX to direct traffic to multiple applications on the same machine.

By default both production and development will start the app on port 1337. It’s good to have separate ports for production and development if not only for telling them appart easier. To change the port on which your Sails JS application listens find the file config/env/production.js and add or uncomment the entry port:80. Of course you can set the port number to whatever you need.

Why do I get CSS import Grunt errors when starting Sails JS in production?

This happened to me on one of my latest projects. I used the assets/styles/importer.less file to @import a couple of extra CSS stylesheets like this:

@import 'login.css';

This worked fine in development mode. However when starting the application in production mode I got the error:

sails js production grunt error broken import

------------------------------------------------------------------------
Aborted due to warnings.
Running "cssmin:dist" (cssmin) task
Warning: Broken @import declaration of "login.css" 
------------------------------------------------------------------------

What’s going on here? Well, cssmin:dist is the hint here. When running in production Sails JS will try to join and minify CSS for optimization. This however fails due to the @import statement.

The solution is to rename the CSS file to a .less extension and import that. This will cause LESS to do it’s magic and the minification process will not fail anymore. In my case I renamed the file to login.less and changed the import statement to

@import 'login.less';

Why is Font Awesome not working on Sails JS production mode?

In your Sails JS application front end it’s very likely that you will have used bower for your dependency management and if you are like me you added Font Awesome for using their wonderful webglyphs as icons.

Again, in development mode everything works fine, but when starting Sails JS in production you see that all the Font Awesome icons are missing. Why? If you turn on your browser’s developer console you will see that there are some errors due to missing files required by Font Awesome (.woff, etc.).

Why aren’t the files there? That’s because in production mode Sails JS does not copy the Font Awesome files to the .tmp (which is where the app actually lives) at the right place.

The solution is to extend the Sails JS build scripts to also copy the necessary Font Awesome files. To do that we first need to create a Grunt task that will copy the files in the right place. Since this is a copy task and Sails JS already has a couple of copy tasks we will add this task in tasks/config/copy.js and it will look like this:

...
fonts: {
 files: [
 {
  expand: true,
  flatten: true,
  src: ['.tmp/public/bower_components/**/fonts/*',],
  dest: '.tmp/public/fonts'
 }]
}
...

This tasks will take all files from the bower_components folder and will copy them in the right place.

To call this task we need to edit the file tasks/register/buildProd.js and insert the new task created like this:

...
'cssmin',
'copy:fonts',
'linkAssetsBuildProd',
...

Font Awesome in place, done!

Why aren’t my Angular JS controllers working anymore in Sails JS production?

Also in the front end, I use most of the times Angular JS. After creating a bunch of controllers which work just fine in development I find that in production they don’t work anymore. Why? Also due to minification of the JS files (and the way I wrote my controllers).

Let's see an example that does not work in production:

app
.controller("LoginCtrl",function($scope, $timeout, $http){
 ...
});

Looks fine, and works until you try to minify the code. The minified version does not work anymore. The problem is the way the dependency injections are written. What do we do?

The solution is to write the controllers (and all other Angular JS directives) in the alternative way like this:

app
.controller("LoginCtrl",['$scope', '$timeout', '$http',function($scope, $timeout, $http){
 ...
}]);

List the dependencies as an array of strings with the last member the function with the controller logic and then restart the Sails JS app in production mode. Voila, it works!

My JS global variables are gone when Sails JS starts in production

In the front end you might want to use some JS global variables. For example I’ve used global variables to store translations for the angular-translate module.

var translations_en = {
"login.username":"Username",
"login.password":"Password"
}

Again this works fine if you sails lift the application in development mode. But, in production mode I started getting JS errors, and very cryptic ones. As before the problem lies in the fact that Sails JS will perform JS minification and obfuscation when starting in production mode. So, the way to properly define JS global variables and have the obfuscated code still work is to do it like this:

window["translations_en"] = {
"login.username":"Username",
"login.password":"Password"
}

The two pieces of code are totally equivalent and the second one will not cause any problems when starting Sails JS in production mode.

How do we start the Sails JS application in the background production mode?

As you’ve probably noticed, whenever you start the Sails JS application both in production and in development you get a console with output from the server. This blocks the console and if you try to close the console then the server also stops.

We need to start the server in background mode. Usually on Linux you do that by adding & at the end of the command, or via nohup. There is a much better way to properly start Sails JS in background. It’s called forever.

forever is tool for ensuring that a given script runs continuously. It’s a Node JS module which you can easily install as a global module like this:

$ [sudo] npm install forever -g

To start the Sails JS application in production mode using forever run the following line:

forever start --uid "nameOfYourApp" app.js --prod

This not only starts the Sails JS application in the background, but also takes care of it and in the case an error causes it to stop it will restart it. The --uid parameter will give a nice name to the process managed by forever. You can use that when sending various commands to forever like for example:

//list managed processes
forever list

//stop process
forever stop nameOfYourApp

//restart the process
forever restart nameOfYourApp

This concludes the tutorial on how to prepare your Sails JS application for production. Hope you find this useful, and if you want to add anything to this list, or if you run into trouble when trying to run your Sails JS app in production mode, don’t hesitate to drop me a comment and I will try to elaborate a solution.

John Negoita

View posts by John Negoita
I'm a Java programmer, been into programming since 1999 and having tons of fun with it.
[jetpack-related-posts]

2 Comments

  1. […] I’ve even published a post on this blog about it some while ago (Preparing your SailsJS application for production). […]

    Reply
  2. […] I’ve even published a post on this blog about it some while ago (Preparing your SailsJS application for production). […]

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top