6

I'm trying to integrate Angular 2 in a Sails Js application. I'm new to both. I have been following this official tutorial here. It works fine in standalone mode with a static http server but when i try to integrate into sails app i get following problems:

1 - How do i refer to angular2 js inside the local node_modules folder. Everytime i do, sails interprets it as a route and gives me a 404 for my scripts. For instance:

<script src="node_modules/angular2/dist/angular2.min.js"></script>

I was able to overcome above issue using cdnjs links for now but i would like to know a better/proper solution.

2 - I added the tsc and tsc -w scripts to my package.json, but even with sails lift --verbose i do not get any output or error. Here is how I added the script to json file:

"scripts": {
    "tsc": "tsc",
    "tsc:w": "tsc -w",
    "debug": "node debug app.js",
    "start": "node app.js"
}

In the end i had to install typescript with -g and compile manually. That worked, but again, it's expected to work with the scripts. It would be great to know what I'm missing.

3 - After jumping through hoops to get rid of the above errors, when i lift the server again, it gives me more 404 error which seem to be coming from system.src.js and that I am unable to figure out. Please see the console screengrab below.

enter image description here

I think I might be making a mistake setting up the angular application directories within sails. Just to make sure we cover everything, here is the directory structure I'm using. The sails app does not have anything in it yet. Which is why the below paths are just for angular related artifacts and assets.

Within the assets folder:

app

│   ├── app.component.ts

│   └── main.ts

Of course the .ts files get compiled to js.

In the sails views folder I have layout.ejs which has following contents:

  .
  .
  .

<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.34.2/es6-shim.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.17/system-polyfills.js"></script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/2.0.0-beta.1/angular2-polyfills.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.17/system.src.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.7/rx.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/2.0.0-beta.1/angular2.dev.js"></script>

  <script>

      System.config({
          packages: {
              app: {
                  format: 'register',
                  defaultExtension: 'js'
              }
          }
      });
      System.import('/app/main')
              .then(null, console.error.bind(console));
  </script>


  .
  .
  .

  <my-app>Loading...</my-app>

In addition to above files, I have also added the tsconfig in the sails root folder.

I have followed the code and directory structure guidelines from the official quickstart tutorial.

Mad
  • 538
  • 1
  • 10
  • 27
xmaestro
  • 1,084
  • 2
  • 16
  • 44

4 Answers4

6

So, for anyone interested, i have resolved the issues like so:

1 - For providing static access to node_modules i created an express middleware (probably use policies for this as well?):

(config/express.js)

var express = require('express');
module.exports.http = {
customMiddleware: function (app) {
    app.use('/node_modules', express.static(process.cwd() + '/node_modules'));
   }
};

2 - I was able to compile already so all good there

3 - For the rxjs related errors, i did some research and found out that rxjs is no longer bundled with angular 2. Therefor, i had to modify the systemjs config a bit to add mapping for rxjs, like so:

(views/layout.ejs)

System.config({
          map: {
              rxjs: 'node_modules/rxjs' // added this map section
          },
          packages: {
              app: {
                  format: 'register',
                  defaultExtension: 'js'
              },
              'rxjs': {defaultExtension: 'js'} // and added this to packages
          }
      });
System.import('/app/main')
              .then(null, console.error.bind(console));
Community
  • 1
  • 1
xmaestro
  • 1,084
  • 2
  • 16
  • 44
5

You need to setup access to your static files. You can check out how, right here. http://sailsjs.org/documentation/concepts/assets

So put those node modules into an asset folder, for which you can then have static access.

However, are you sure you want to do this with Sails? As far as I know Sails is a fullblown MVC framework, which you won't really need if you only want to use it as a backend for Angular. I'd recommend using something like Express instead.

Luka Jacobowitz
  • 22,795
  • 5
  • 39
  • 57
  • I thought of that but i don't want to move modules inside, that's too much effort and not the best way to maintain, don't you think? – xmaestro Feb 01 '16 at 13:45
  • I'm afraid, it's the only way known to me. Angular is a client-side framework and needs access to those modules. With express, you can give access to any directory. – Luka Jacobowitz Feb 01 '16 at 13:49
  • Is there some sort of sails policy that would let me have access? Say something like "if the route starts with a segment 'node_modules' dont route"? – xmaestro Feb 01 '16 at 14:01
  • From what I can tell, the documentation has no mention of this. However there might be a way to use some custom middlewar. – Luka Jacobowitz Feb 01 '16 at 14:03
  • Maybe this could help? http://stackoverflow.com/questions/21097679/confusion-about-web-application-ports/21099224#21099224 – Luka Jacobowitz Feb 01 '16 at 14:04
  • Or this? http://stackoverflow.com/questions/20543252/how-to-serve-a-static-folder-in-sails-js – Luka Jacobowitz Feb 01 '16 at 14:04
  • So i am able to provide static access to node_modules but i am still getting those 404 errors shown in the image in original post. – xmaestro Feb 02 '16 at 07:17
  • Even if i put the node_modules in assets folder, i still get those errors. – xmaestro Feb 02 '16 at 07:17
  • 1
    The main question to choose either ejs or angular is, if you want to create your html server side or on the client side. So the server side template engines (ejs, jade, handlebars, mustachej, ...) are fine and cool, but if you decide that you want send JSON from server to client and render those data on the client side than you have to choose angular or some other client side js library – harry Feb 09 '16 at 10:36
  • @Luka Jacobowitz Sails is a server-side (backend) framework, built on Express, and works with just about any front-end tool, library, or framework you can imagine. It supports static asset routing by default- no need to install or configure anything else. Also worth mentioning is that Sails provides an asset pipeline out of the box. This helps you automate repetitive tasks like compiling TypeScript or LESS files, while sticking with established conventions and avoiding reinventing the wheel on your project. (See http://sailsjs.org/documentation/concepts/assets for more info.) – mikermcneil Oct 29 '16 at 13:30
3

You can use the JavaScript files that are provided in the folder node_modules/angular2/bundles:

<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/rxjs/bundles/Rx.js"></script>
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>
<script src="node_modules/angular2/bundles/router.dev.js"></script>
<script src="node_modules/angular2/bundles/http.dev.js"></script>

This should answer to your first question.

Regarding the second question, elements you put in the scripts block of your package.json file are aliases for commands. The tsc -w one waits for updates in TypeScript files and automatically compiles them. This command must be started in background... For example with: npm run tsc:w.

Hope it helps you, Thierry

Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • Well, i tried that already and tried again but gives me 404 : ""NetworkError: 404 Not Found - "http://localhost:1337/node_modules/angular2/bundles/angular2-polyfills.js" – xmaestro Feb 01 '16 at 13:30
  • I have not added any server side routes yet, just to make it clear – xmaestro Feb 01 '16 at 13:30
  • From your question, I saw your tried `node_modules/angular2/dist/...` and not `node_modules/angular2/bundles/...`. No? – Thierry Templier Feb 01 '16 at 13:32
  • It won't matter, because it needs to be in the asset folder. – Luka Jacobowitz Feb 01 '16 at 13:33
  • Check my other answer. – Luka Jacobowitz Feb 01 '16 at 13:33
  • @ThierryTemplier I tried the correct path to the module files, i double checked. – xmaestro Feb 01 '16 at 13:47
  • @ThierryTemplier But the `tsc` should run and compile before sails server starts. Am i wrong with this approach? That is how they did in the tutorial though. – xmaestro Feb 01 '16 at 13:53
  • @R.Hussain these files are statically served so I think the server can be start before compiling typescript files. But they must be there when loading your application in a browser... – Thierry Templier Feb 01 '16 at 13:57
  • @ThierryTemplier So i was able to resolve this. Please have a look at my answer to make sure i am not missing anything. – xmaestro Feb 02 '16 at 07:45
  • Cool! I had a look at your answer. Why do you need to configure RxJS within SystemJS in your HTML. I think that including the corresponding file in a ` – Thierry Templier Feb 02 '16 at 08:04
  • Well, i think systemjs uses rxjs and needs a path to it because if i don't give it that in config, it shows weird 404 errors looking for rxjs as you see in the image i posted (http://i.stack.imgur.com/Tf6Pn.png) – xmaestro Feb 02 '16 at 12:22
  • I don't think so ;-) Angular2 (from `angular2/src/facade/async` module) tries to load `rxjs/Subject` through an import. The latter delegates to SystemJS to load this class but it can't... – Thierry Templier Feb 02 '16 at 12:58
  • @R.Hussain the problem with 404 angular files not found is that when Sails lifts it Grunt deletes all the files in .tmp then rebuilds the project from scratch, so what happens is Sails server starts before the build is finished and the files are not there that's why you get 404. If you wait for a little while your page should load without any errors. – netlander Feb 03 '16 at 15:10
1

(1) For the first question:

The problem with 404 angular files not found is that when Sails lifts Grunt deletes all the files in .tmp then rebuilds the project from scratch, so what happens is Sails server starts before the build is finished and the files are not there that's why you get 404. If you wait for a little while your page should load without any errors.

If waiting get too long use these scripts from CDN:

  <script src="https://rawgithub.com/systemjs/systemjs/0.19.6/dist/system.js"></script>
  <script src="https://code.angularjs.org/tools/typescript.js"></script>
  <script src="https://code.angularjs.org/2.0.0-beta.1/angular2-polyfills.js"></script>
  <script src="https://code.angularjs.org/2.0.0-beta.1/Rx.js"></script>
  <script src="https://code.angularjs.org/2.0.0-beta.1/angular2.dev.js"></script>
  <script src="https://code.angularjs.org/2.0.0-beta.1/router.dev.js"></script>
  <script src="https://code.angularjs.org/2.0.0-beta.1/http.dev.js"></script>

(2) Second question: Run tsc in a separate console window like this:

npm run tsc:w

(3) The third problem by adding the following to components where it's needed:

import 'rxjs/add/operator/map';
netlander
  • 1,128
  • 1
  • 11
  • 12