web-dev-qa-db-ja.com

Angular 2:バンドルを使用するようにSystemJSに指示する方法は?

Angular 2 RC7アプリがあり、SystemJSを使用してJavaScriptファイルをロードしています。

これは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);

これで、すべてのアプリロジックを含むapp.bundle.min.jsというバンドルと、使用される依存関係を含むdependencies.bundle.min.jsを作成しました。

ファイルを個別にインポートするのではなく、これらのファイルを使用するようにSystemJSに指示するにはどうすればよいですか?

私はこれを交換しようとしました:

<script>
  System.import('app').catch(function(err){ 
    console.error(err); 
  });
</script>

と:

<script src="production/dependencies.bundle.min.js"></script>
<script src="production/app.bundle.min.js"></script>

私のindex.htmlでは、それは機能していません。 System.import...スクリプトブロックをindex.html内に保持している限り、アプリは読み込まれますが、バンドルの代わりに個別のファイルが使用されます。

私もこれを変更しようとしました:

map: {

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

しかし、それもうまくいきませんでした。

これは、バンドルが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(){});

どういうわけか、バンドルを指すようにSystemJS構成内のマッピングを変更する必要があると思いますか?どうすればよいですか?

14
Glenn Utter

SystemJS構成のmapおよびpackagesによると、

_System.import('app')
_

ファイル_app/main.js_のリクエストに変換されます。ただし、生成されたApp Bundleを調べると、このモジュールが実際に次のように登録されていることがわかります。

_System.registerDynamic("dist/main.js" ...
_

バンドルがdistフォルダー内の_.js_ファイルから生成されたためです。

この不一致が、モジュールがスクリプトバンドルから読み込まれない理由です。

可能な解決策の1つは、_.ts_および_.js_ファイルを常にapp内の_.ts_、dist内の_.js_に保持することです。そうすれば、systemjsはdistについてのみ知る必要があります。変更する必要があるsystemjs.config.jsの唯一の部分は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',
_

それが機能することを確認するために、私は angular quickstart example から始めて、これらのタスクに_gulpfile.js_を追加しました:

  1. gulp-TypeScript プラグインを使用してTypeScriptをdistにコンパイルします。

    _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. systemjs構成ファイルをdistフォルダーにコピーします。これにより、アプリコードと一緒にバンドルされ、本番環境で使用できるようになります(bundleではなくbuildStaticを使用しているため、これが必要です)

    _gulp.task('bundle-config', function() {
      return gulp.src('app/configs/systemjs.config.js')
        .pipe(gulp.dest('dist/configs'));
    });
    _
  3. systemjsビルダーでバンドルを生成します。

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

依存関係のないアプリバンドルを生成するために_[dist/**/*]_構文を使用していることに注意してください-gulpfile.js内のものは異なり、いくつかの依存関係を含むはるかに大きなバンドルを生成します-それが意図的かどうかはわかりません。

次に、_index-production.html_からのこれらの変更を使用して_index.html_を作成しました。

  1. _<script>_の_systemjs.config.js_タグを削除-バンドルからインポート

  2. バンドルの_<script>_タグを_<head>_に追加します

    _<script src="production/dependencies.bundle.min.js"></script>
    <script src="production/app.bundle.min.js"></script>
    _
  3. インライン_<script>_を追加して、構成とアプリモジュールをインポートします。

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

bundleで生成されたバンドルは何もインポートせず、コードを実行しないため、「app」モジュールのインポートが必要です。これらは、buildStaticで生成された「sfx」バンドルとは異なり、すべてのモジュールを後でインポートできるようにするだけです。

また、このスクリプトブロックは_<body>_要素の後の_<my-app>_にある必要があります。そうしないと、_<my-app>_要素がまだ作成されていない場合、appが早く開始されます(または、import('app')「ドキュメント準備完了」イベントで呼び出すことができます)。

あなたはgithubで完全な例を見つけることができます: https://github.com/fictitious/test-systemjs-angular-gulp

27
artem