Trying to setup my own Angular2+Typescript (+SystemJS+Gulp4) starter project has hit a roadblock for me. I encountered issues when transitioning from compiling TypeScript in the same folder as JavaScript with access to the node_modules
folder, to organizing everything in a dist
folder (with dist/js
for compiled JavaScript and dist/js/lib
for vendor files like angular2.dev.js
, http.dev.js
, router.dev.js
, Rx.js
, system.src.js
, etc.).
You can view the full project on GitHub at souldreamer/event-planner.
Would appreciate it if someone could review and point out where I might be going wrong. It seems likely that the issue lies in the SystemJS
configuration in index.html
, as different configurations either result in no loading of boot.js
(even though network tab shows everything loaded) or errors such as
core_1.Component is not a function
or core_1.Input is not a function
when attempting to include InputComponent
.
Note: This is not a duplicate problem, as extensive research and attempts have been made over the past few days to resolve it, despite similarities with other questions found online.
Below are relevant snippets from the project, should you prefer not to go through the entire codebase:
TypeScript
compilation (Gulp4
task):function tsCompile() { var tsResult = gulp .src(['./app/**/*.ts', './typings/**/*.ts']) .pipe(sourcemaps.init()) .pipe(tsc(tsc.createProject('tsconfig.json'))); return merge([ tsResult.dts.pipe(gulp.dest('./typings/typescriptApp.d.ts')), tsResult.js .pipe(sourcemaps.write('.')) .pipe(gulp.dest('./dist/js')) ]); }
tsconfig.json
{ "compilerOptions": { "outDir": "dist/js", "target": "ES5", "module": "system", "moduleResolution": "node", "sourceMap": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "removeComments": false, "noImplicitAny": true, "suppressImplicitAnyIndexErrors": true }, "exclude": [ "node_modules" ] }
index.html
<head> <base href="/"> <link rel="stylesheet" href="styles.css"> <!-- inject:libs --> <!-- add wanted libs to gulpfile --> <!-- this is replaced by the gulp task runner --> <!-- lib order: --> <!-- angular2-polyfills, system.src, Rx, --> <!-- angular2.dev, router.dev, http.dev --> <!-- endinject --> <script> System.config({ baseUrl: './', // same result with this omitted transpiler: 'typescript', // same result with this omitted defaultJSExtensions: true, bundles: { './js/lib/angular2.dev.js': ['angular2/*'] }, packages: { js: { format: 'register', defaultExtension: 'js' } }, paths: { 'angular/http': './js/lib/router.dev.js', 'angular/router': './js/lib/http.dev.js', 'angular2/*': './js/lib/angular2.dev.js', 'rx/*': './js/lib/Rx.js' } }); System.import('js/boot') .then( function() {console.log('loaded')}, console.error.bind(console) ); </script> </head> <body> <main-app>Loading...</main-app> </body> </html>
boot.ts
(the actualAngular2
app functionality works fine, included here for clarity)import {bootstrap} from 'angular2/platform/browser'; import {AppComponent} from './components/app.component'; bootstrap(AppComponent, []);
app.component.ts
(the actualAngular2
logic operates smoothly, included here for context)import {Component} from 'angular2/core'; import {InputComponent} from './input.component'; @Component({ selector: 'main-app', template: `<h1>Hi!</h1> <input-component label="A"></input-component> <input-component label="B"></input-component> `, directives: [InputComponent] }) export class AppComponent { }
input.component.ts
(the component's role within the Angular2 app is intact, provided here for completeness)import {Component, Input} from 'angular2/core'; @Component({ selector: 'input-component', template: ` <label [attr.for]="inputName">{{label}} <input #input [attr.id]="inputName" type="text"></label> `, styles: [ `label { color: red; }` ] }) export class InputComponent { public static latestId: number = 0; private inputId: number = InputComponent.latestId; @Input() public label: string = ''; constructor() { InputComponent.latestId++; } get inputName(): string { return 'input-' + this.inputId; } }