Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 Typescript app throws 404 on components when js extension not specified

I just started to play around with Angular2, and ran into a weird component file extension problem:

Let's use the 5 minutes quickstart demo from angular.io (I'll reproduce the code here for reference).

File structure

angular2-quickstart
|- app
|  |- app.component.ts
|  |- boot.ts
|
|- index.html
|- package.json
|- tsconfig.json

package.json

{
  "name": "angular2-quickstart",
  "version": "1.0.0",
  "scripts": {
    "tsc": "tsc",
    "tsc:w": "tsc -w",
    "lite": "lite-server",
    "start": "concurrent \"npm run tsc:w\" \"npm run lite\" "
  },
  "license": "ISC",
  "dependencies": {
    "angular2": "2.0.0-beta.0",
    "systemjs": "0.19.6",
    "es6-promise": "^3.0.2",
    "es6-shim": "^0.33.3",
    "reflect-metadata": "0.1.2",
    "rxjs": "5.0.0-beta.0",
    "zone.js": "0.5.10"
  },
  "devDependencies": {
    "concurrently": "^1.0.0",
    "lite-server": "^1.3.1",
    "typescript": "^1.7.3"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "target": "ES5",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  },
  "exclude": [
    "node_modules"
  ]
}

app/app.component.ts

import {Component} from 'angular2/core';

@Component({
    selector: 'my-app',
    template: '<h1>My First Angular 2 App</h1>'
})
export class AppComponent { }

app/boot.ts

import {bootstrap}    from 'angular2/platform/browser'
import {AppComponent} from './app.component'

bootstrap(AppComponent);

index.html

<html>

  <head>
    <title>Angular 2 QuickStart</title>

    <!-- 1. Load libraries -->
    <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>

    <!-- 2. Configure SystemJS -->
    <script>
      System.config({
        packages: {        
          app: {
            format: 'register',
            defaultExtension: 'js'
          }
        }
      });
      System.import('app/boot')
            .then(null, console.error.bind(console));
    </script>

  </head>

  <!-- 3. Display the application -->
  <body>
    <my-app>Loading...</my-app>
  </body>

</html>

This works like a charm, but exposes the whole file structure, including node_modules and the configuration, which seems like a bad idea.

So I tried to expose only the app folder. To achieve that, I did the following:

  • Copy the referenced javascript files in an app/scripts folder
  • Move the index.html in app
  • Change the references paths in this file
  • Change the lite script in package.json to lite-server --baseDir app

When running this, everything worked, except that angular2-polyfills.js returned :

Error: XHR error (404 Not Found) loading http://localhost:3000/app.component(…)
  run @ angular2-polyfills.js:138
  zoneBoundFn @ angular2-polyfills.js:111
  lib$es6$promise$$internal$$tryCatch @ angular2-polyfills.js:1511
  lib$es6$promise$$internal$$invokeCallback @ angular2-polyfills.js:1523
  lib$es6$promise$$internal$$publish @ angular2-polyfills.js:1494
  lib$es6$promise$$internal$$publishRejection @ angular2-polyfills.js:1444
  (anonymous function) @ angular2-polyfills.js:243
  run @ angular2-polyfills.js:138zoneBoundFn @ angular2-polyfills.js:111
  lib$es6$promise$asap$$flush @ angular2-polyfills.js:1305

Of course, if I ask for http://localhost:3000/app.component.js the file is returned correctly.

So my question is: why doesn't the .js extension get appended to app.component, resulting in this error, where that worked when the server baseDir was the root of the project ? Did I miss some configuration option ?

like image 792
xlecoustillier Avatar asked Dec 20 '15 12:12

xlecoustillier


4 Answers

You can configure the path to your app folder. In my case, I'm using angular 2 to produce a mobile version of our app and had to configure System like so:

System.config({
            paths: {
                'app/*': './js/mobile/dist/*'
            },
            packages: {        
              app: {
                format: 'register',
                defaultExtension: 'js'
              }
            }
          });
          System.import('app/main')
                .then(null, console.error.bind(console));

As you can see, I decided to map "app" to "dist" where I have my compiled js files to keep them separate from the ts files.

like image 93
headwinds Avatar answered Nov 21 '22 00:11

headwinds


This problem may be caused by JetBrains WebStorm when refactoring files to new locations. It seems to append the .ts extension on imports.

So, keep your new files in their places but check every file's imports.

All of your imports should resemble this

import {MyComponent} from './Components/MyComponent';

And not this

import {MyComponent} from './Components/MyComponent.ts';
like image 36
Alex Hopkins Avatar answered Nov 21 '22 00:11

Alex Hopkins


In my boot.ts file I changed this line:

import {AppComponent} from './app.components'

and it works. I reported to Google today as well.

like image 27
Steve Avatar answered Nov 20 '22 22:11

Steve


In my case, it is resolved when added module.id

@Component({
    ***moduleId: module.id,***
    providers : [MyService],
    templateUrl: 'sandbox.component.html',
})
like image 30
HydTechie Avatar answered Nov 21 '22 00:11

HydTechie