Contents


The busy JavaScript developer's guide to Sails.js, Part 1

Build and deploy a basic web app with Sails

Get started with Sails in your local development environment, then deploy it to Bluemix

Comments

Content series:

This content is part # of 4 in the series: The busy JavaScript developer's guide to Sails.js, Part 1

Stay tuned for additional content in this series.

This content is part of the series: The busy JavaScript developer's guide to Sails.js, Part 1

Stay tuned for additional content in this series.

Ever find yourself wandering in the cheese aisle of a gourmet shop, overwhelmed by the impressive display of cheeses from all over the world? It's a nice problem to have, but the trouble is in deciding which of them to bring home.

A cheese selection so abundant that it's overwhelming is a perfect example of the paradox of choice, the principle that says that while having no choice is bad, having too many choices is equally as bad, and can sometimes lead consumers to give up choosing altogether.

Developers looking for a Node.js framework or library are faced with this very issue, a virtual embarrassment of riches. It can be difficult to know which of the many options to choose from, much less how to get started with a Node.js framework, or which factors will help you decide whether it's the right fit.

Choosing Sails.js

Given the plethora of options, I had to wade through a few alternatives before settling on Sails.js. I like Sails because it embraces some of the ideas that have made the Rails framework so successful, while maintaining a distinct Node.js flair. In particular, Sails uses layered development and convention over configuration, two development techniques popularized by Rails and similar frameworks. Sails also integrates several other Node.js packages for key components, which means you don't necessarily have to learn the framework from scratch. Another plus is the fact that the documentation for Sails.js is continually improving, a key indicator that I look for from any open source project.

In this first installment, I'll focus on how Sails approaches layered development. Future installments will introduce convention over configuration and other conveniences of coding with Sails.

The new MVC

The Sails approach to layered development is different from what many traditional web developers might expect. In fact, Sails is one of an emerging breed of frameworks that redefines expectations of web application development by turning MVC on its ear. Instead of the MVC components residing on the server, as in a traditional MVC architecture, Sails puts the models and controllers on the server, while the views live on the client tier. Sails also sees the "view" as a more generic concept; it could be HTML, but it could also be a mobile application written in native iOS or Android.

This reconfiguring of the traditional MVC architecture achieves the very thing that architects and developers have long sought from application servers: a single place for business logic and validation, and a common interface for multiple clients.

Instead of the server shipping HTML back to the client, Sails just ships data, typically in the form of JSON or XML. The client (either a mobile app or a single-page web app written with a client-side JavaScript framework like AngularJS) then consumes that data and presents it in the manner most suited to the client's look and feel. For most clients, the data representation format will be JSON because many single-page web and mobile clients are written using JavaScript, and can easily consume JSON. It's also not hard to employ a different data representation format like XML if necessary.

This reconfiguring of the traditional MVC architecture achieves the very thing architects and developers have long sought from application servers: a single place for business logic and validation, and a common interface for multiple clients. The server needs only to project data elements in a representation recognizable to the client, and this approach provides an easy way to do traditional business logic and data validation through HTTP endpoints.

The HTTP API example app

This new architecture, what I call an HTTP API, is similar to the RESTful style, but it's not actually REST — not, at least, according to Roy Fielding's definition of REST. REST relies on the exchange of hypermedia as the principal vehicle of application state (this is the Hypertext As The Engine Of Application State, or HATEOAS, principle — quite possibly the worst acronym ever invented). But an HTTP API system surrenders some of the flexibility and "generic client" capability that REST offers in exchange for a simpler model.

Unlike a REST system, HTTP API clients do require some deductive knowledge of the system they're communicating with. They need to know the expected results and available endpoints ahead of time. It's contrary to a REST architecture, but I find that the trade-off for simplicity is worthwhile.

In an HTTP API, all communication between client and server takes place over HTTP. For the example app, I'll use JSON as the data format exchanged and standard HTTP verbs to indicate actions (GET as read, POST as insert, PUT as update, and DELETE as delete). I'll also use HTTP headers as the mechanism for conveying out-of-band information like authentication data and so on. I will, however, still store some state data on the server side (contrary to a traditional REST design), and the data exchanged will all be JSON and assumed to be specific to this system.

Consumers of the HTTP API example — mobile apps, single-page JavaScript apps, or even the other servers that want access to the data contained therein — will know about the JSON types I'll be shipping back to them. This is as opposed to the more REST-ish hypertext/HATEOAS focus, which suggests that any app should be able to "discover" the information being sent back. More importantly, consumers will know the subsequent HTTP endpoints to which their data can be sent, retrieved, or modified.

While evaluating Sails.js, I spent some time experimenting with it. So without further ado, let's start learning the ropes of Sails.

What you'll need: Prerequisites and setup

I'm going to expect that you are somewhat familiar with the principles and terminology of REST and RESTful architectures; you don't have to be a zealot, but you should be comfortable using HTTP "in the raw" to submit GET requests, POST requests, and so on. The idea of looking at an in-flight HTTP request shouldn't scare you.

I also assume that you are comfortable with JavaScript, Node.js, and npm, the package manager for JavaScript code and libraries. You should have Node.js installed on your development machine of choice, know how to run Node.js apps locally, and be able to "npm-install" your way out of a paper bag. While it will be helpful if you've read up on so-called modern JavaScript (specifically, the JavaScript described by Douglas Crockford in JavaScript: The Good Parts, or one of the many books or tutorials it's spawned), in truth, you'll need only a working knowledge of JavaScript to get started with Sails.

For your development environment, make sure Node.js is up to date on your machine (as of this writing, mine reports version 0.12.7), and that you have the latest version of npm installed (mine is version 2.12.1). While the Node.js community obviously tries to keep versions backward-compatible, there's no guarantee that the code I write here will work with significantly earlier versions of the technology. Caveat emptor.

Install Sails.js and MongoDB

The only installation required to use Sails.js is to install it globally to the npm cache, like so: npm install -g Sails.js.

Once you've done that you'll have a new utility command, sails, available for your use. Like npm, sails is a command-line utility written in JavaScript for Node.js. It acts as a kind of single-source utility for doing several things with the Sails.js framework — like creating a new application, running the application, running the application in a debug loop, generating new components for the app, and so on. When installing Sails.js via npm, make sure to use the -g option. Otherwise, it will only be installed to the current project directory, and this is one of those rare cases where the utility really needs to be global.

While you're waiting for the Sails.js framework to download and install, take a minute to be sure that you have MongoDB set up in your development environment. If you don't, now is a good time to download an installation appropriate for your target platform.

Note that Sails.js uses more than just a MongoDB back end; in fact, right out of the box, Sails.js uses a lightweight disk-based format. It's not a recommended setup for production use, but works delightfully well for examples like this one. It will take a minute to get to the part of this series where MongoDB comes in, but you'll be glad to have it when I do.

That's the basic setup for now. You'll need to add a Cloud Foundry install and a Bluemix login to the mix later in this tutorial, when I deploy the local app to the Bluemix cloud.

Check the installation

Is Sails.js done installing? Verify it with the command sails version.

As of this writing, the latest version of Sails.js is 0.11.0. As long as the above command yields anything other than an error, Sails is installed and ready to go.

Sails.js says "Hello, world!"

Tradition holds that the very first thing a programmer does when learning a new language or environment is to write the simplest possible program in that language: a Hello World application. Fortunately, Sails generates a Hello World as the basic application scaffolding when you create a new app. I can use this to verify that the Sails infrastructure is working. In a nod to agile development strategies, I'll also deploy the scaffolding to the cloud (Bluemix, in this case) as part of a "release early, release often" strategy.

Create a basic Sails.js app

Getting a new Sails.js app is pretty simple. Note that by default, the scaffolding will generate a more traditional web application, where the server-generated HTML is sent back to the client. While that's useful in its own right, if the goal is to build an HTTP API app that is client-agnostic, I want to ensure that there's no accidental "leakage" tying the client to the server. The best way to do that is to build the server with zero client components anywhere in the project. In Sails.js, that's as simple as setting your default configuration to --no-frontend.

The downside of using the --no-frontend option is that I won't have a visual way to verify that the scaffolding works. I'll want that verification when I deploy the app to Bluemix. So for this first installment, I'll create an app that has the pretty HTML front-end scaffolding, but in future installments, I'll run with the assumption that the app was built without any front-end pieces. (The difference is just what's populated in the generated views directory, so it's not as big a deal as it may seem.)

Enough talk. Let's get sailing!

From the directory where you want the code to live on your development machine, issue a new command via the sails command line, then name your app: sails new hello-sails.

After you do this, Sails will think for a second, then should respond with a message like: "Created a new Sails app 'hello-sails'!" (If anything else comes back, something is probably wrong with your Sails.js installation.) In the target directory, which is inferred from the application name, you'll see that Sails.js laid down a number of directories and files. I'll explore most of these in greater detail throughout the series. For now, I'll just familiarize you with the basics of a Sails application.

Generally, it's safe to assume that the scaffolding won't have any problems (so long as nobody touches it), but it's helpful to know how to run the app locally. So let's kick off our journey with a "sails lift."

Figure 1. Running Sails.js locally
Screenshot shows Sails.js     output confirming that the default web  app is running on the local machine
Screenshot shows Sails.js output confirming that the default web app is running on the local machine

Pretty, no? Personally, I like the use of color, and additionally, it's quite the impressive display of ASCII art. More important is that this little ASCII painting confirms that Node.js is successfully running our scaffolded application on the local machine, on port 1337. Hit it with a browser and the default Sails.js web page will appear, complete with links back to the main Sails homepage and documentation.

Deploy Sails.js to the cloud

Running on a local machine is not the same as deploying your code to a production (or production-like) server, and this is where the cloud comes into play. For this series, I'll use Bluemix as the cloud host. It seems apropos, and Bluemix is an easy platform to use for hosting Node.js-based applications.

Bluemix also happens to be based on Cloud Foundry, so if you haven't already, now is the time to install the Cloud Foundry client (cf). You'll want it running on the same machine where your Sails.js code is hosted.

After you've installed the client, verify the installation by running cf--version; at the time of this writing, the version echoed back was 6.12.2.

As mentioned, you'll also need a Bluemix login to deploy the app to Bluemix. Once you've got your credentials, log in to Bluemix and push the code from your local hello-sails directory into the Bluemix cloud.

Listing 1. cf into Bluemix
Teds-MBP15:hello-sails ted$ cf login
API endpoint: https://api.ng.bluemix.net

Email> ted@tedneward.com

Password> 
Authenticating...
OK

Select an org (or press enter to skip):
1. developerWorks
2. ted@tedneward.com

Org> 1
Targeted org developerWorks

Targeted space Ted Neward


                   
API endpoint:   https://api.ng.bluemix.net (API version: 2.27.0)   
User:           ted@tedneward.com   
Org:            developerWorks   
Space:          Ted Neward

The cf tool will also need to know the API endpoint to use for deployment. If cf can't figure that out, you can manually set the endpoint (api.ng.bluemix.net) via the command cf api api.ng.bluemix.net.

Two useful files

Once you've logged in and set the API endpoint, you'll use cf push to deploy the scaffolded Sails.js app to the cloud. Cloud Foundry will just need a few parameters in order to deploy the application correctly. Rather than typing those repeatedly (which grows tiresome), create a manifest file (manifest.yml). This will contain information like the application name to use on the Bluemix cloud, the hostname to use for a subdomain (if it's different from the application name), how much RAM to reserve for executing, and so on.

The simple manifest file for the example:

---
applications:
- name: tedneward-sailsIntro
  host: tedneward-sailsIntro
  memory: 256M
  command: node app.js

Another useful file that Cloud Foundry recognizes is .cfignore. This contains the list of files or directories that shouldn't be pushed up from the local app to the cloud. For now, just file that information away for future reference.

With all that in place, all that's left is to do a cf push and let the push do its thing. (The output from this can be sometimes quite impressive in length, as the code must be packaged up, uploaded, unpacked, then installed on the cloud instance, which in turn means running an npm install on the cloud instance, which generates a ton of results. As a result, only about the first 20 and the last half-dozen lines are displayed here.)

Listing 2. cf push to Bluemix
Using manifest file /Users/ted/Projects/sails-intro/code/hello-sails/manifest.yml

Updating app tedneward-sailsIntro in org developerWorks / space Ted Neward as ted@tedneward.com...
OK

Using route tedneward-sailsIntro.mybluemix.net
Uploading tedneward-sailsIntro...
Uploading app files from: /Users/ted/Projects/sails-intro/code/hello-sails
Uploading 31M, 11773 files
Done uploading               
OK

Stopping app tedneward-sailsIntro in org developerWorks / space Ted Neward as ted@tedneward.com...
OK

Starting app tedneward-sailsIntro in org developerWorks / space Ted Neward as ted@tedneward.com...
-----> Downloaded app package (24M)
-----> Downloaded app buildpack cache (18M)

-----> IBM SDK for Node.js Buildpack v2.5-20150902-1526
       Based on Cloud Foundry Node.js Buildpack v1.5.0
-----> Creating runtime environment
       NPM_CONFIG_LOGLEVEL=error
       NPM_CONFIG_PRODUCTION=true
       NODE_MODULES_CACHE=true
-----> Installing binaries
       engines.node (package.json):  unspecified
       engines.npm (package.json):   unspecified (use default)
       
. . .

App tedneward-sailsIntro was started using this command `node app.js`

Showing health and status for app tedneward-sailsIntro in org developerWorks / space Ted Neward as ted@tedneward.com...
OK

requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: tedneward-sailsIntro.mybluemix.net
last uploaded: Mon Oct 5 01:36:54 UTC 2015
stack: lucid64
buildpack: SDK for Node.js(TM) (ibm-node.js-0.12.7)

Assuming you've uploaded and installed all the components correctly, you should see a new subdomain on the Bluemix cloud (in my case, it's http://tedneward-sailsIntro.mybluemix.net). The new subdomain will respond to an HTTP GET / request by producing the Sails.js sample hello page.

Conclusion

With the scaffolding in place, I'm set up to begin extending and improving the example app. Thanks to the work done so far, I'll be able to deploy the new code to the Bluemix cloud each time I finish a new segment. Remember the principle, "always be shipping" — or put another way, "release early, release often." Each time I push code to the server for others to use, I'm creating opportunities for people to find bugs, verify that I'm headed in the right direction with the code, and so on. Using a well-established cloud foundation makes it trivial to ship, since I've done most of the work up front. With a simple cf push, the latest version of the Sails app will be aloft and waiting for HTTP clients to find and use it.

The next installment will feature the Sails.js models. Getting to know the models will also introduce you to a hefty amount of Sails convention, called blueprints or the Sails Blueprint API. Like its inspiration, Rails, Sails favors convention over configuration, which means I'll be able to build models, and get some useful functionality out of the box, without having to write a ton of configuration files or code.

I have just a scaffold now, but the example app that will take shape over the next several tutorials will be a blog engine — with a twist. Rather than build the engine as a traditional server-side web app, I'll develop it as an HTTP API. The API packs all the technology I'll need into the back end, leaving the client-side code to be determined by whatever front-end tool somebody wants to write.

For now, it's time to pause. Given the name of the framework, let us not say "so long" but the more appropriate "bon voyage."


Downloadable resources


Related topics


Comments

Sign in or register to add and subscribe to comments.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development, Open source, Mobile development, Cloud computing
ArticleID=1018803
ArticleTitle=The busy JavaScript developer's guide to Sails.js, Part 1: Build and deploy a basic web app with Sails
publish-date=07122016