exk0730 exk0730 - 4 months ago 21
TypeScript Question

Relative Paths for SystemJS & ES module imports

I'm having an issue with importing Angular2 components when using SystemJS and ES import syntax.

Project structure:

ROOT
|_src
|_client
|_app
|_frameworks
|_il8n
|_analytics
|_main
|_components
|_pages
|_utility


Let's say I have a file:
ROOT/src/client/app/frameworks/il8n/language-service.ts
and another file:
ROOT/src/client/app/main/pages/login/login.ts
. In login.ts I want to import language.ts, so one way to do that is like so:

//login.ts
import { LanguageService } from '../../../../frameworks/il8n/language-service';


Another way to do that, using barrels, is like so:

//login.ts
import { LanguageService } from '../../../../frameworks/index';


where
frameworks/index.ts
is doing
export * from './il8n/language-service';


I don't want to do
../../../
etc every time I need to import something; it would be nice if I could just do
import { LanguageService } from 'frameworks';


So far, I've been able to get my build process working using SystemJS's "map" option like so:

map: {
frameworks: 'src/client/app/frameworks/index',
components: 'src/client/app/main/components/index',
pages: 'src/client/app/main/pages/index'
}


However, my IDE is complaining (all IntelliSense functionality is completely broken) anytime I do something like:

`import { LanguageService } from 'frameworks';`


Here is my tsconfig.json file:

{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"declaration": false,
"removeComments": true,
"noLib": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"sourceMap": true,
"pretty": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitUseStrict": false,
"noFallthroughCasesInSwitch": true,
"baseUrl": "./src",
"paths": {
"frameworks": ["client/app/frameworks"],
"components": ["client/app/main/components"],
"pages": ["client/app/main/pages"],
"utility": ["client/app/main/utility"]
}
},
"compileOnSave": false
}


Is there a way to satisfy both my IDE and the SystemJS build configuration so that I can do "simple" imports?

Answer

So, this question was based around the Angular2 Seed (Advanced) repo found here. I posted an issue there as well (where you can see the exact fix). Long story short:

You need TypeScript 2.0 to use the paths and baseUrl options in your tsconfig file. Then in your SystemJS config file, you need to add some configuration to the paths and packages options as follows:

packages: {
  ...
  frameworks: { defaultExtension: js, main: index.js }
  ...
},
paths: {
  ...
  frameworks: 'relative/path/to/frameworks/folder'
  ...
}

index.ts is a file INSIDE your frameworks folder which exports the modules in that directory. For example, if you had a language.component.ts file somewhere inside your frameworks directory, in the frameworks/index.ts file you would do:

export * from 'path/to/language.component';.

This allows you to do import {LanguageComponent} from 'frameworks'; in your project (as long as you are outside the frameworks directory).

Hope this helps!