Je viens de commencer à jouer avec Angular2, et j'ai rencontré un problème étrange d'extension de fichier composant:
Utilisons la démo quickstart de 5 minutes de angular.io (je vais reproduire le code ici pour référence).
Structure de fichier
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>
Cela fonctionne comme un charme, mais expose la structure de fichier entière, y compris node_modules
et la configuration, ce qui semble être une mauvaise idée.
J'ai donc essayé d'exposer uniquement le dossier app
. Pour y parvenir, j'ai procédé comme suit:
app/scripts
index.html
dans app
lite
dans package.json
par lite-server --baseDir app
Lors de l'exécution de cette opération, tout a fonctionné, sauf que angular2-polyfills.js
a renvoyé:
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
Bien sûr, si je demande http://localhost:3000/app.component.js
, le fichier est renvoyé correctement.
Ma question est donc la suivante: pourquoi l'extension .js
n'est-elle pas ajoutée à app.component
, ce qui entraîne cette erreur, qui a fonctionné lorsque le serveur baseDir était la racine du projet? Ai-je oublié une option de configuration?
Vous pouvez configurer le chemin d'accès à votre dossier d'application. Dans mon cas, j'utilise angular 2 pour produire une version mobile de notre application et je devais configurer System de la manière suivante:
System.config({
paths: {
'app/*': './js/mobile/dist/*'
},
packages: {
app: {
format: 'register',
defaultExtension: 'js'
}
}
});
System.import('app/main')
.then(null, console.error.bind(console));
Comme vous pouvez le constater, j’ai décidé de mapper "app" sur "dist", là où j’ai mes fichiers js compilés pour les conserver séparés des fichiers ts.
Ce problème peut être dû à JetBrains WebStorm lors du refactoring de fichiers vers de nouveaux emplacements. Il semble ajouter l'extension .ts sur les importations.
Alors, gardez vos nouveaux fichiers à leur place, mais vérifiez les importations de chaque fichier.
Toutes vos importations doivent ressembler à ceci
import {MyComponent} from './Components/MyComponent';
Et pas ça
import {MyComponent} from './Components/MyComponent.ts';
Dans mon fichier boot.ts
j'ai changé cette ligne:
import {AppComponent} from './app.components'
et il fonctionne. J'ai signalé à Google aujourd'hui aussi.
Dans mon cas, il est résolu lorsque ajouté module.id
@Component({
***moduleId: module.id,***
providers : [MyService],
templateUrl: 'sandbox.component.html',
})
Il vous manque app/main.ts. Ce ne sont que quelques lignes, il est donc assez facile de rater le Quickstart.
J'ai eu la même erreur avec chrome, après avoir tiré mes cheveux pendant un moment, j'ai essayé de désactiver adblock et cela a fonctionné par la suite. Si vous avez adblock, c'est probablement le coupable
après avoir essayé de nombreuses autres solutions suggérées par d’autres, j’ai découvert que cela peut casse par points dans les noms de fichiers et que ces deux solutions ont fonctionné pour moi.
defaultJSExtensions: true,
mais defaultJSExtensions est une propriété qui sera obsolète à l’avenir et deuxièmement:
packages: {
'.': {
defaultExtension: 'js'
}
}