Search code examples
typescriptangularbase-urles6-module-loader

Imports other than angular2 deps breaks webapp compilation


In my angular 2 application I have issues with importing dependencies other than angular or my application components. (e.g. angular2-moment)

I have <base href="/">

Application runs via main (compilation.js contains all app modules):

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

As soon as I inject anything from node_modules other than angular it makes the compilation fail. and I get a 404 from main.

import {Component} from "angular2/core";
import {ROUTER_PROVIDERS} from 'angular2/router';
import {HTTP_PROVIDERS} from "angular2/http";
import "rxjs/Rx";
import {HeaderComponent} from "./header/header.component";
import {HomeComponent} from "./home/home.component";
import {SidebarComponent} from "./side-bar/sidebar.component";
import {RouteConfig, ROUTER_DIRECTIVES} from "angular2/router";
import {enableProdMode} from "angular2/core";
//import {TimeAgoPipe} from 'angular2-moment'; <-- this breaks main (404)

The console error:

GET http://localhost:3001/main 404 (Not Found)
scheduleTask    @   angular2-polyfills.js:126

enter image description here

tsconfig is:

{
  "compilerOptions": {
    "target": "es5",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false,
    "outDir": "app/",
    "outFile": "app/compilation.js",
    "declaration": true
  },
  "exclude": [
    "node_modules",
    "typings/main",
    "typings/main.d.ts"
  ]
}

Any help to save more hair on my head would be highly appreciated.


Solution

  • OK. Here is the answer but still not sure why things have to be so hard?

    Solution only applies to bootstrap and angular moment and don't think all components will be the same.

    1. Define a path for each dependency in System.config
    2. Define moment to be loaded as a global

    Within index.html

    System.config({
        packageConfigPaths: ['node_modules/*/package.json'],
        paths: {
            'moment': '/node_modules/moment',
            'angular2-moment/*': '/node_modules/angular2-moment/*',
            "ng2-bootstrap/ng2-bootstrap": "node_modules/ng2-bootstrap/ng2-bootstrap"
        },
        packages: {
            app: {
                format: 'register',
                defaultExtension: 'js'
            }
        },
        meta: {
            moment: {
                format: 'global',
                globals: {
                    moment: 'moment'
                }
            }
        }
    });
    

    Within ng2:

    // you can use ng2-bootstrap file just fine
    import {PAGINATION_DIRECTIVES} from 'ng2-bootstrap/ng2-bootstrap';
    // but for angular moment also mention extension. 
    import {DurationPipe} from 'angular2-moment/DurationPipe.js';
    

    Now with all this:

    @Component({
        "selector": "my-component",
        directives: [PAGINATION_DIRECTIVES],
        pipes: [DurationPipe],
        "templateUrl": "app/templates/my-template.html",
    })
    

    I think I am pulling my hair out more now than when I asked the question.

    Someone please clarify some of this for me.