2016-09-14 29 views
12

Mam aplikację Angular 2 RC7, w której używam SystemJS do ładowania plików JavaScript.Angular 2: W jaki sposób poinformować SystemJS, aby używał pakietu?

To moja obecna konfiguracja 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 stworzyliśmy pakiet o nazwie app.bundle.min.js, który zawiera wszystkie moje logikę aplikacji i dependencies.bundle.min.js zawierający zależności używane.

W jaki sposób powiedzieć systemowi SystemJS, aby używał tych plików zamiast pojedynczo importować pliki?

Próbowałem zastępując w ten sposób:

<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 index.html, ale to nie działa. Dopóki przechowuję blok skryptu System.import... w pliku index.html, aplikacja ładuje się, ale używa pojedynczych plików zamiast pakunków.

Próbowałem też zmieniając w ten sposób:

map: { 

    // Our app is within the app folder 
    app: 'production/app.bundle.min.js', 

ale to nie działało.

ten sposób wiązki są generowane przy użyciu 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, muszę jakoś zmienić mapowania w mojej konfiguracji SystemJS wskazać kierunku wiązki? Jak mam to zrobic?

+0

Trudno powiedzieć, nie wiedząc dokładnie, jak pakiety są generowane – artem

+0

Dodałem zadanie haustem na moje pytanie. –

Odpowiedz

22

Według map i packages w swojej SystemJS config,

System.import('app') 

przekłada się na wniosku o pliku app/main.js. Jednak, jeśli spojrzeć na generowanej wiązki aplikacji, można zauważyć, że ten moduł jest faktycznie zarejestrowana jako

System.registerDynamic("dist/main.js" ... 

ponieważ wiązka została wygenerowana z .js plików w folderze dist.

Ta niedopasowanie powoduje, że moduły nie są ładowane z pakietu skryptów.

Jednym z możliwych rozwiązań jest zawsze .ts i .js plików w oddzielnych folderach - .ts w app, .js w dist. W ten sposób systemjs będą wiedzieć tylko o dist: jedyną częścią systemjs.config.js że trzeba zmienić mapowanie jest app:

// 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 to działa, zacząłem od angular quickstart example i dodał gulpfile.js z następujące zadania:

  1. kompilacji maszynopis język dist użyciu gulp-typescript wtyczki.

    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')); 
    }); 
    
  2. kopia systemjs plik konfiguracyjny do dist folderu, tak aby zostaną dołączone wraz z kodem aplikacji i będzie dostępny w produkcji (nie jest to konieczne, ponieważ używasz bundle a nie buildStatic)

    gulp.task('bundle-config', function() { 
        return gulp.src('app/configs/systemjs.config.js') 
        .pipe(gulp.dest('dist/configs')); 
    }); 
    
  3. generowania wiązki o systemjs producentów:

    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(){}); 
    

Należy zauważyć, że używa on składni [dist/**/*] do generowania pakietu aplikacji bez żadnych zależności - ten w pliku gulpfile.js jest inny i generuje znacznie większy pakiet, który zawiera pewne zależności - nie wiem, czy jest to zamierzone, czy nie.

Potem stworzyliśmy index-production.html z tych zmian z index.html:

  1. usunąć <script> znacznik do systemjs.config.js - sprowadzamy go od wiązki

  2. dodać <script> tagów dla wiązek w <head>

    <script src="production/dependencies.bundle.min.js"></script> 
    <script src="production/app.bundle.min.js"></script> 
    
  3. dodaj w linii <script> że importuje config i aplikacji moduł:

    <script> 
        System.import('dist/configs/systemjs.config.js').then(function() { 
        System.import('app').catch(function(err){ console.error(err); }); 
        }); 
    </script> 
    

importowaniem moduł aplikacji „” jest konieczne, ponieważ pakiety generowane z bundle nie importować niczego i nie uruchomić dowolny kod - są one jedynie podejmowania wszystkie moduły dostępne do późniejszego importu, w przeciwieństwie do pakietów "sfx" wygenerowanych za pomocą buildStatic.

Również ten blok skryptu musi być w elemencie <body> po <my-app>, inaczej app rozpocznie się zbyt wcześnie, gdy element <my-app> nie został jeszcze utworzony (alternatywnie import('app') można nazwać na „dokument gotowy” wydarzeniem).

można znaleźć pełny przykład na github: https://github.com/fictitious/test-systemjs-angular-gulp

+0

Niesamowita odpowiedź. Dziękuję Ci bardzo! Twoje rozwiązanie działa jak urok. –

+0

@artem to jest możliwe z tym rozwiązaniem do debugowania plików ts w przeglądarce? – Yvan

+0

@ Yvan tak, musisz zainstalować i skonfigurować gulp-sourcemaps. Zaktualizowałem przykładowe repozytorium. – artem