Angular 2:如何告诉SystemJS使用捆绑包?

Gle*_*ter 14 javascript bundle systemjs angular

我有一个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);
Run Code Online (Sandbox Code Playgroud)

现在我创建了一个app.bundle.min.js包含所有app逻辑的包,其中dependencies.bundle.min.js包含使用的依赖项.

如何告诉SystemJS使用这些文件而不是单独导入文件?

我试过替换这个:

<script>
  System.import('app').catch(function(err){ 
    console.error(err); 
  });
</script>
Run Code Online (Sandbox Code Playgroud)

有:

<script src="production/dependencies.bundle.min.js"></script>
<script src="production/app.bundle.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

在我的index.html中,但那不起作用.只要我将System.import...脚本块保留在index.html中,该应用程序就会加载但使用单个文件而不是捆绑包.

我也试过改变这个:

map: {

    // Our app is within the app folder
    app: 'production/app.bundle.min.js',
Run Code Online (Sandbox Code Playgroud)

但那也不起作用.

这是使用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(){});
Run Code Online (Sandbox Code Playgroud)

我怀疑我必须以某种方式更改我的SystemJS配置中的映射以指向捆绑包?我该怎么做呢?

art*_*tem 25

根据mappackages你的SystemJS配置,

System.import('app')
Run Code Online (Sandbox Code Playgroud)

转换为文件请求app/main.js.但是,如果查看生成的应用程序包,您会看到该模块实际上已注册为

System.registerDynamic("dist/main.js" ...
Run Code Online (Sandbox Code Playgroud)

因为捆绑包是从.js文件dist夹中的文件生成的.

这种不匹配是未从脚本包加载模块的原因.

一个可能的解决方案是要始终保持.ts.js文件在不同的文件夹- .tsapp,.jsdist.这样,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',
Run Code Online (Sandbox Code Playgroud)

为了检查它是否有效,我从angular quickstart示例开始,并添加gulpfile.js了以下任务:

  1. dist使用gulp-typescript插件将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'));
    });
    
    Run Code Online (Sandbox Code Playgroud)
  2. 将systemjs配置文件复制到dist文件夹中,以便将其与应用程序代码捆绑在一起,并且可以在生产中使用(这是必需的,因为您正在使用bundle而不是buildStatic)

    gulp.task('bundle-config', function() {
      return gulp.src('app/configs/systemjs.config.js')
        .pipe(gulp.dest('dist/configs'));
    });
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用systemjs builder生成bundle:

    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(){});
    
    Run Code Online (Sandbox Code Playgroud)

请注意,它使用[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>
    
    Run Code Online (Sandbox Code Playgroud)
  3. 添加内联<script>导入配置和应用程序模块:

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

导入'app'模块是必要的,因为生成的bundle bundle不会导入任何东西并且不运行任何代码 - 它们只是使所有模块可以在以后导入,而不像'sfx'生成的bundle buildStatic.

此外,此脚本块需要位于<body>after <my-app>元素中,否则app<my-app>在尚未创建元素时过早启动(或者,import('app')可以在'document ready'事件上调用).

你可以在github上找到完整的例子:https://github.com/fictitious/test-systemjs-angular-gulp