I'm working on an Angular 2 with Typescript project using SystemJS. Right now I find often we're having to do things like '../../../
' to load components from other modules depending on how deeply nested we are in a given component. It would seem like using SystemJS's map setting would allow me to have application-wide modules available for import without that horrible relative pathing approach, but I can't determine definitively if I can do that. I'm also open to other ways to solve this.
Basically what I'd like to do is something like this:
import {Component} from '@angular/core';
import {SecureHttpClient} from 'mySecurityModule'; //No ../../../
@Component({
moduleId: module.id,
selector: 'my-selector',
templateUrl: 'my.component.html'
})
export class MyComponent {
constructor(private client: SecureHttpClient) {
}
}
I tried the configuration below but it doesn't work (TS compilation fails).
(function (global) {
System.config({
paths: {
// paths serve as alias
'npm:': 'node_modules/'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
app: 'app',
// angular bundles
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
'@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js',
// other libraries
'rxjs': 'npm:rxjs',
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api',
'@ng-bootstrap/ng-bootstrap': 'npm:@ng-bootstrap/ng-bootstrap/bundles/ng-bootstrap.js',
// Internal Modules
'mySecurityModule': 'app/secure/secure.module'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './main.js',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
},
'angular-in-memory-web-api': {
main: './index.js',
defaultExtension: 'js'
}
}
});
})(this);
I know there is likely other ways to do this, but again can't find anything definitive and it's a problem I'd really like to solve. Thanks again!
You can setup typescript compiler to use base URL and import from there. In tsconfig.json
add:
"compilerOptions": {
"baseUrl": "./",
...
}
then you can use app root as an absolute path. Something like
import {SecureHttpClient} from 'app/mySecurityModule';
instead of:
import {SecureHttpClient} from '../../../mySecurityModule';
Actual paths might be different for you.
However, I would recommend using some sort of Import extension for your editor (for example, AutoImport for VSCode), since some tools (AoT, CLI) might have an issue with this. Hopefully things will improve as tools get more mature (;