Integrating Angular (4) with Sails.js

Update #6 April 13, 2017: I have updated this post as well as the sample code repo to use Angular 4.0.2.

Update #5 November 23, 2016: I have updated this post as well as the sample code repo to use Angular 2.2.1.

Update #4 September 23, 2016: I have updated this post as well as the sample code repo to use Angular 2.0.0.

Update #3 September 4, 2016: I have updated this post as well as the sample code repo to use Angular 2 RC6.

Update #2 August 6, 2016: I have also set up the sails sample projects here in this repo

Update #1 August 6, 2016: This post has been updated for Angular 2 RC4.

Recently I had a project requirement where I had to work with Sails.js, a full-blown nodejs framework based on Express.js. The client wanted to integrate Angular js as front-end to it.

So, to cut it short, I started researching about some sample Angular and Sails integrations and I found plenty of them. But the thing is, all of those tutorials are for Angular 1.x. And it makes sense because as of writing this post, Angular 2 is still in beta. And I was easily able to get around working with Angular 1 and Sails but I had a hard time integrating Angular 2 within a Sails app.

As you might already know that Angular 2 is based on TypeScript which is a superset of javascript. It makes use of the latest ES6 js engine and is also backward compatible with ES5 and classic javascript constructs.

So, enough of the intro, let’s get down to the real stuff. I will start and go ahead assuming that you have already setup a sails application. If you find yourself lacking there, go ahead and follow the steps over here to set yourself up.

The first order of business would be installing TypeScript as a global node module. Do that like so:

Now, you will need to add following dependencies to your package.json file.

After that run npm install to install the dependencies.

Add the following to a new file tsconfig.json which you should place in the sails application root.

Now, in your layout.ejs file add the following scripts in the head.

What the above code does is to load the Angular 2 and required ES6 modules. The /app/main is the entry script for angular that we still have to create.

After that, within the body tag of the same file, add the application template tag, like so:

The my-app tag above represents the angular app which we still have to build.

But before we move on to that, if you lift the server and see the console you will see many 404 errors for the above scripts we added.

Actually, sails by default does not have a static access entry for the /node_modules folder. We will create one. Add the following code to a new file express.js in config/express.js.

We are basically creating an Express middleware to allow static access to the node_modules folder. Now if you lift the server again you won’t see the 404 errors.

Now, the next step is to move on to the Angular app which we referred to above. For that let’s start with creating a directory named app  in assets folder. Let’s create three files in there, app.component.ts, app.module.ts and main.ts. 

These are TypeScript files which we will later compile to javascript for our Systemjs config to work. Add the following code to main.ts.

And add the following in app.component.ts.

Lastly, fill in the module file app.module.ts with the following code.

Since this post is just about setting up Angular 2 with Sails, I will let skip what the code is about. It’s just a simple Angular Hello world and you can find it’s explanation on the official site.

Now that we have set up everything correctly, it’s time to compile the TypeScript files. For that let’s navigate to the project directory and run

This will transpile .ts files to .js. After that, you can lift the sails server and you should see the “My First Angular 2 App” text somewhere in the page when you browse to it. For the transpiler to compile automatically upon the change in its files run the watcher like so:

And that’s it!

alexey

alexey

Application developer, movie buff, occasional reader and a huge Manchester United fan.
alexey
  • jhades

    Hello, I would like to ask you your opinion on something. I’ve read somewhere (here -> https://kev.inburke.com/kevin/dont-use-sails-or-waterline/) that Sails is a framework to be avoided, specially because of its ORM. Is even if half of what is mentioned in the article is still true? like counting the rows in a table loads all records in memory and loops to count them, instead of doing select count(*) from table.

    Just wanted to know your thoughts on Sails and if you noticed any of the things mentioned in the article at all? (I’ve personally never used Sails just read about it)

    • dxmaestro

      Thanks for the comment. I think that depends on a lot of factors. I saw the post, most of the bugs have been fixed. There are obviously be limitations which we tend to categorize as drawbacks when you develop something which is supposed to be portable. Same is with Waterline, it was designed with portability (maybe there is a better term perhaps?) in mind. One day you are on MySql, next you wanna switch to Mongo. It provides an interface that allows us to work with that.

      Like he mentioned in the article, most of us did not notice that 50ms delay in POST request, count me one of those 😀 . Probably because like you, i have just started working with it.

      • @jhades:disqus @dxmaestro:disqus Hey guys, I just ran across this and wanted to follow up and address some of the points mentioned here, since comments don’t always make it on to kev.inburke.com.

        First, I think it’s important to come to the author’s defense: Kevin Burke is no longer at Shyp, so he’s no longer using Node.js (which I imagine he’s [pretty relieved about](https://twitter.com/ekrubnivek/status/775721195618471936)). It was clear he was unhappy using Node.js/Sails, and that he fundamentally rejects some of the reasons why folks like me think Node is fantastic. I completely understand the feeling of being tied down to a technology you don’t like, and it can make you feel pretty awful (I’m sure a lot of us have been there in the past). But despite having every reason not to care, while he was at Shyp, Kevin still helped track down some issues on Sails, and I’m really grateful for that.

        ### 50 ms issue
        re: the 50ms issue: This was resolved over a year ago, within a couple of weeks from the time it was reported. (The delay was largely due to a lack of clarity on both sides as to what was being reported). The real source of the issue had nothing to do with “sleeping”, or even the setTimeout code that was linked to on GitHub. (See https://github.com/balderdashy/sails/issues/3205#issuecomment-217309292 for details.)

        Thus the real learning experience from this was that we needed to pin the semver ranges of all 3rd party dependencies (which is not something that happens by default, if you’re using NPM’s --save). Arguably, for some projects it’s not ideal– but this made us realize that Sails is far too mission critical for far too many companies, including our own, not to lock things down. (There are a lot of good ways to manage your dependencies in Node. Personally, these days, I’ve been using a [whitelist of trusted dependency SVRs](https://github.com/mikermcneil/kit#kit-deps) to make sure we’re using trusted versions of dependencies that our team has manually audited.)

        Back to the point: Unfortunately, the original GitHub issue was posted on Reddit and Hacker News, with a click-bait topic string. Worse, it was posted without sufficient context, and so as it gained traffic, was misunderstood as being somehow connected with the code that was linked.

        But in fact, as I already mentioned, that code [had nothing to do with the underlying cause of the bug](https://github.com/balderdashy/sails/issues/3205#issuecomment-217309292)- it just happened to include a “setTimeout”. And since a lot of the folks reading through the Reddit and HN posts must not have realized that in Node.js, setTimeout is non-blocking, the actual facts kind of got lost underneath the noise and generic anti-Node comments. What I mean by “non-blocking” is that using setTimeout for one request does not prevent the server from handling other incoming requests (this is different from something like “sleep”, which does not actually exist in JavaScript).

        That’s not to say that using setTimeout is a good practice in everyday development, or anything like that. In front-end code, it’s been my experience that setTimeouts are a red flag that something else might be broken under the covers. But sometimes they are not a hack at all, and are actually necessary (i.e. because you need a timer for a feature.) Skipper uses several timers as a way to optimistically dump untapped, unexpected, or misbehaved incoming file upload streams to help prevent DDoS attacks. So its code does include setTimeouts.

        Anyway, I hope this doesn’t come across as me minimizing the issue– it was definitely adding latency to API requests, and I applaud Shyp for investing time in helping make sure their underlying open source tools are performant. As for why no one noticed for a while, my best guess is that it was probably because POST requests usually involve doing something dynamic, and so have higher latency on average. For example, the POST request to Google Analytics when you load a GitHub repo takes ~210ms from my home internet. So unless you’re doing a thorough benchmarking pass, or trying to diagnose something else, you’re very unlikely to notice the difference of 50ms in your logs (and you definitely wouldn’t notice it without any tools). Also, in some cases, the 50ms would actually be swallowed, and so wouldn’t actually make a different in the total request time.

        ### Security policy

        re:
        > “No documented responsible disclosure policy, or information on how security vulnerabilities are handled.”

        With @joepie91’s and @rachaelshaw’s help, I put together an official security policy in September, 2015:

        + https://github.com/balderdashy/sails/issues/2830
        + http://sailsjs.com/security-policy

        ### .count()

        re:
        > The .count function used to work by pulling the entire table into memory and checking the length of the resulting array.

        This is the behavior of the built-in polyfill in Waterline core. Since 2012, it has been overridable by implementing a count function in your database adapter. This never should have been relied upon in any of the adapters maintained by our team at all, but when Sails grew rapidly in popularity in 2013, Cody and I were left maintaining a framework that, at that time got downloaded 25,000 times per month (these days it’s more like 50k-70k). We regrouped as fast as we could, but it took us a while to catch up as the code base and community grew– not just as far as battle-testing the framework for performance, but also as far as the philosophy towards polyfills, populates, and query performance in the ORM, and the kind of code quality we need to be verifying in pull requests before merging. For more on that, see https://github.com/balderdashy/waterline/pull/1052#issuecomment-195144878. We’ve spent a good chunk of this year working on this, and other improvements to the ORM, as well as to [performance of Sails apps in general](https://groups.google.com/forum/#!topic/node-machine/mprKoJ6jPzk).

        In Sails v1, the .count() polyfill will be removed in favor of a descriptive error message letting a user know that, if they want to use count(), they should contact the maintainer of the adapter, do a pull request, fork the adapter, or choose a different one.

        I’ll stop there to avoid going on too much of a tangent, but like I said above, please let me know if I can provide more clarification on any of the other points and how they’ve been dealt with, and I’d be happy to.

  • Thanks for the tutorial! In what folder of your sails application do you create this package.json file? there is already one in the root of the app, but I assume this is for server side only. Also, I think instead of loading the angular script from node_modules, you could just add it to assets/js/dependencies.

    • dxmaestro

      Thanks for stopping by. Well, you don’t need to create package.json separately. We use the one that comes with sails. I could add it to assets folder but that would creat a bigger code trace in repo and moreover we should use package manager whenever possible for latest code and all the goodies that come with it 🙂

  • Yannis Weishaupt

    Don’t forget to replace by Loading… in layout.ejs

  • thili

    run “tsc”, I got error,
    node_modules/angular2/src/facade/promise.d.ts(1,10): error TS2661: Cannot re-export name that is not defined in the module.

    • dxmaestro

      As mentioned here (https://github.com/angular/angular/issues/6795) , TS 1.8 requires Angular beta .7 or higher.

      • thili

        this page not available

        • dxmaestro

          Sorry about that. In any case, just update to angular beta .8 and it should work.

          • thili

            I already updated

  • dizhar

    Hi, how to I setup sails to compile typescript files to javascript on lift?

  • Andrew Lewman

    Hi thank for the tutorial. But now i very need to integrate Angular 2 with sails.js, it’s now working.
    When i add “angular” to package.json and install it, sails server don’t lift!
    This is what I see
    SyntaxError: /home/xdevand/www/trying-a2/someapp/node_modules/angular2/ts/package.json: Unexpected token <

    • Andrew Lewman

      Done, I fix it by “subo rm -rf node_modules/angular2/ts”

  • Edwin Santiago

    excellent friend, just was looking for a tutorial with angular 2 and I’m happy because you use the latest upgrade of RC4, I hope you can help me in case you have problems because

  • Francis Gendreau

    in angular 2.0.0-rc.4, bootstrap has been moved to platform-browser-dynamic. The first line in assets/app/main.js needs to be corrected accordingly.

    • dxmaestro

      Hi. Thanks for pointing that out. I have update the post as well as the sample code repo to use RC6 now.

      • Francis Gendreau

        thx for the update to rc6. In the dependencies, router-deprecated should be rc.2 not rc.6 🙂

        • dxmaestro

          Fixed that. Thanks 🙂

  • Baptiste Legouix

    Hello, very good job with this article.

    What about socket.io ?

    • dxmaestro

      Sorry. What about it?

      • Jeff Magsuci

        how to connect angular2-webpack with sails-socket.io

  • You forgot to mention that Loading… needs to be placed in one of the templates. Also, there’s a typo in one paragraph: app.module.ys

    • dxmaestro

      Thanks for pointing that out. I have fixed that.

  • Hi, thank you for the good job that helps us very much.
    I would like to ask you on the possibility to make an Angular2+Sails project server side rendering (isomorphic, universal) ?
    Your views will be very helpful.
    Thank you.

  • Sudhir Jena

    Hi,
    I would also like to know (if you could throw some light) on how to integrate an angular 2 app generated by angular-cli into sails.js. With angular 1, i generally followed the following:
    1. Install angular and other front-end dependencies (like material-deisgn-lite, toastr, etc) with bower
    2. Manage sails (backend) dependencies with npm
    3. Use grunt bower tasks to copy required bower components into assets/js/vendor directory
    4. Use default sails grunt tasks to package and inject all files in assets like js, styles, images, etc.
    5. Creating a view with ng-app tag or modifying existing layout.ejs to have ng-app tag
    6. Configure routes to use the above view if layout.ejs is not included by default

    However with angular 2 the above streamlined setup becomes a bit convoluted because of:
    1. typescript has to be compiled to js upon build
    2. webpack is used for packing asstes

    Any help is greatly appreciated.

    • dxmaestro

      Hi Sudhir,

      To be honest with you, i am fairly new to whole JS development scene. But i have some observations which i would like to share with you.

      Referring to your list above, with angular 2, you will be merging steps 1 and 2. You manage angular as well as sails deps using npm. All other steps will still work.

      As for the Typescript code, that gets compiled and minified into one single js file using SystemJs Builder(if you are using SystemJs as module loader) or Webpack. Both work fine. Angular 2 provides support for both JIT compilation and also has AOT compilation using cli.

      I hope that clarifies it a bit 🙂

  • Lahiru

    Hi,
    Now this shows loading and in console below error shows up. Any help?

    Error: eval@[native code]
    invoke@http://localhost:1337/node_modules/zone.js/dist/zone.js:232:31
    run@http://localhost:1337/node_modules/zone.js/dist/zone.js:114:49
    http://localhost:1337/node_modules/zone.js/dist/zone.js:502:60
    invokeTask@http://localhost:1337/node_modules/zone.js/dist/zone.js:265:40
    runTask@http://localhost:1337/node_modules/zone.js/dist/zone.js:154:57
    drainMicroTaskQueue@http://localhost:1337/node_modules/zone.js/dist/zone.js:401:42
    g@http://localhost:1337/node_modules/core-js/client/shim.min.js:8:10017
    http://localhost:1337/node_modules/core-js/client/shim.min.js:8:10139
    k@http://localhost:1337/node_modules/core-js/client/shim.min.js:8:14294
    Evaluating http://localhost:1337/app/main.js
    Error loading http://localhost:1337/app/main.js

    • optimguy

      I am getting similar error when i try to add routing. please guide on how to add routing to this tutorial.

    • EDWIN MAURICIO QUISHPE MALDONA

      I got the same error when I try to add forms in my app. So how we should to routing other extra packages like a forms, I know that we put access to node_modules with the middleware, but I mind that something is no working properly.

  • Chunkations

    when I run tsc it says
    ../angular2/app/environment_app.component.ts(1,31): error TS2307: Cannot find module ‘angular2/core’.
    ../angular2/app/environment_main.ts(1,25): error TS2307: Cannot find module ‘angular2/platform/browser’.

    • pablo cordoba

      Just install angular cli
      npm install -g @angular/cli

  • Alex Bui

    How we move “app” folder out of assets directory?

  • Bhargav Narayan

    Hi,
    Firstly, Thanks for this great tutorial.
    Currently I’ve an application built using sails.js and angular. Now I need to add few more features to it using angular 2.
    I’ve a stand alone app built in angular2 without any server integration. All routes are handled at client-side in this app. When I tried to integrate this angular app with my sails app, I’m unable to navigate to the routes defined in angular app.
    I couldn’t find a way to navigate to different routes.
    Any help will be appreciated.
    Thanks.

  • b1kjsh

    why wouldn’t you set this up with webpack to watch your typescript and update js files? The reason I ask is that in your last step to complie the typescript it doesn’t simply work by just typing in tsc in a console in the app directory. you have to give it parameters… and even then i haven’t been able to get it to complie with just that.

    Also, it seems that I get 404 errors from the app folder which makes me think that there’s a step missing somewhere to add this folder so it’s public. Still researching that though.

  • dizhar

    Does anyone know how dynamic URL work with both Angular2 and Sails.js together

    For example, I set a Slug URL like this ‘/meme/:id/:title’: ‘MemeController.index’. However, when I type in the following URL http://localhost:1337/meme/3/daniel. I get an error Uncaught ReferenceError: System is not defined.

  • Tawab Shakeel

    How to add more components in this particular project?

  • dizhar

    Does anyone know how to setup ahead-of-time (AOT) compilation with Sails.js + Angular4?