Angular 2: Jak powiedzieć SystemJS używać pakietu?
Mam aplikację Angular 2 RC7, w której używam SystemJS do ładowania plików JavaScript.
To jest moja obecna konfiguracja dla SystemJS:
(function (global) {
System.config({
defaultExtension: 'js',
defaultJSExtensions: true,
paths: {
'npm:': 'node_modules/'
},
// Let the system loader know 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',
// Other libraries
'rxjs': 'npm:rxjs',
'ng2-translate': 'node_modules/ng2-translate'
},
// Tell the system loader how to load when no filename and/or no extension
packages: {
app: { main: './main.js', defaultExtension: 'js' },
rxjs: { defaultExtension: 'js' },
'ng2-translate': { defaultExtension: 'js' }
}
});
})(this);
Teraz stworzyłem pakiet o nazwie app.bundle.min.js
, który zawiera całą moją logikę aplikacji i dependencies.bundle.min.js
, który zawiera używane zależności.
Jak powiedzieć SystemJS, aby używał tych plików zamiast importować pliki indywidualnie?
Próbowałem zastąpić to:
<script>
System.import('app').catch(function(err){
console.error(err);
});
</script>
Z:
<script src="production/dependencies.bundle.min.js"></script>
<script src="production/app.bundle.min.js"></script>
W moim indeksie.html, ale to nie pracuję. Dopóki będę trzymał System.import...
blok skryptu w indeksie.html, aplikacja ładuje się, ale używa pojedynczych plików zamiast pakietów.
Próbowałem też zmienić to:
map: {
// Our app is within the app folder
app: 'production/app.bundle.min.js',
Ale to też nie zadziałało.
W ten sposób pakiety są generowane za pomocą Gulp:
gulp.task('inline-templates', function () {
return gulp.src('app/**/*.ts')
.pipe(inlineNg2Template({
UseRelativePaths: true,
indent: 0,
removeLineBreaks: true
}))
.pipe(tsc({
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": true,
"noImplicitAny": false,
"suppressImplicitAnyIndexErrors": true
}))
.pipe(gulp.dest('dist'));
});
gulp.task('bundle-app', ['inline-templates'], function() {
var builder = new systemjsBuilder('', 'app/configs/systemjs.config.js');
return builder
.bundle('dist/**/* - [@angular/**/*.js] - [rxjs/**/*.js]', 'production/app.bundle.min.js', {
minify: true,
mangle: true
})
.then(function() {
console.log('Build complete');
})
.catch(function(err) {
console.log('Build error');
console.log(err);
});
});
gulp.task('bundle-dependencies', ['inline-templates'], function() {
var builder = new systemjsBuilder('', 'app/configs/systemjs.config.js');
return builder
.bundle('dist/**/*.js - [dist/**/*.js]', 'production/dependencies.bundle.min.js', {
minify: true,
mangle: true
})
.then(function() {
console.log('Build complete');
})
.catch(function(err) {
console.log('Build error');
console.log(err);
});
});
gulp.task('production', ['bundle-app', 'bundle-dependencies'], function(){});
Podejrzewam, że muszę jakoś zmienić mapowanie w mojej konfiguracji SystemJS, aby wskazać na pakiety? Jak to zrobić?
1 answers
Zgodnie z map
i packages
w konfiguracji SystemJS,
System.import('app')
Tłumaczy się na żądanie pliku app/main.js
. Jeśli jednak spojrzysz na wygenerowany pakiet aplikacji, zobaczysz, że ten moduł jest rzeczywiście zarejestrowany jako
System.registerDynamic("dist/main.js" ...
Ponieważ pakiet został wygenerowany z .js
plików w folderze dist
.
Ta niezgodność jest powodem, dla którego twoje Moduły nie są ładowane z pakietu skryptów.
Jednym z możliwych rozwiązań jest zawsze zachować .ts
i .js
pliki w osobnych folderach - .ts
W app
, .js
W dist
. W ten sposób systemjs będzie musiał wiedzieć tylko o dist
: jedynej części systemjs.config.js, które trzeba zmienić to app
mapowanie:
// Let the system loader know where to look for things
map: {
// Our app is compiled to js files in the dist folder
app: 'dist',
Aby sprawdzić, czy działa, zacząłem od angular quickstart przykład i dodałem gulpfile.js
z tymi zadaniami:
-
Skompiluj typescript do
dist
za pomocą wtyczkigulp-typescript .var gulp = require('gulp'); var typescript = require('typescript'); var tsc = require('gulp-typescript'); var systemjsBuilder = require('systemjs-builder'); gulp.task('tsc', function () { return gulp.src(['app/**/*.ts', 'typings/index.d.ts']) .pipe(tsc({ "target": "es5", "module": "commonjs", "moduleResolution": "node", "sourceMap": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "removeComments": true, "noImplicitAny": false, "suppressImplicitAnyIndexErrors": true })) .js.pipe(gulp.dest('dist')); });
-
Skopiuj plik konfiguracyjny systemjs do Folder
dist
, więc będzie dołączony wraz z kodem aplikacji i będzie dostępny w produkcji (jest potrzebny, ponieważ używaszbundle
, a niebuildStatic
)gulp.task('bundle-config', function() { return gulp.src('app/configs/systemjs.config.js') .pipe(gulp.dest('dist/configs')); });
-
Generuj Pakiety za pomocą systemjs builder:
gulp.task('bundle-app', ['bundle-config', 'tsc'], function() { var builder = new systemjsBuilder('', 'app/configs/systemjs.config.js'); return builder .bundle('[dist/**/*]', 'production/app.bundle.min.js', { minify: true, mangle: true }) .then(function() { console.log('Build complete'); }) .catch(function(err) { console.log('Build error'); console.log(err); }); }); gulp.task('bundle-dependencies', ['bundle-config', 'tsc'], function() { var builder = new systemjsBuilder('', 'app/configs/systemjs.config.js'); return builder .bundle('dist/**/* - [dist/**/*.js]', 'production/dependencies.bundle.min.js', { minify: true, mangle: true }) .then(function() { console.log('Build complete'); }) .catch(function(err) { console.log('Build error'); console.log(err); }); }); gulp.task('production', ['bundle-app', 'bundle-dependencies'], function(){});
Zauważ, że używa składni [dist/**/*]
do generowania pakietu aplikacji bez żadnych zależności - tej w Twoim pliku gulpfile.js jest inny i generuje znacznie większy pakiet, który zawiera pewne zależności - Nie wiem czy jest zamierzony czy nie.
Potem stworzyłem index-production.html
z tymi zmianami z index.html
:
-
Remove
<script>
tag forsystemjs.config.js
- importujemy go z paczki -
Dodaj
<script>
tagi dla pakietów w<head>
<script src="production/dependencies.bundle.min.js"></script> <script src="production/app.bundle.min.js"></script>
-
Dodaj inline
<script>
, który importuje konfigurację i moduł aplikacji:<script> System.import('dist/configs/systemjs.config.js').then(function() { System.import('app').catch(function(err){ console.error(err); }); }); </script>
Importowanie modułu 'app' jest konieczne, ponieważ pakiety generowane z bundle
niczego nie importują i nie uruchamiają żadnego kodu - robią tylko wszystkie moduły dostępne do importu później, w przeciwieństwie do pakietów' sfx ' generowanych przez buildStatic
.
Również ten blok skryptów musi znajdować się w <body>
po elemencie <my-app>
, w przeciwnym razie app
rozpocznie się zbyt wcześnie, gdy element <my-app>
nie zostanie jeszcze utworzony (alternatywnie, import('app')
można wywołać w zdarzeniu 'document ready').
Pełny Przykład znajdziesz na GitHubie: https://github.com/fictitious/test-systemjs-angular-gulp
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-16 02:14:09