【问题标题】:Angular 2 deploy with SystemJS and Gulp is too heavy使用 SystemJS 和 Gulp 部署 Angular 2 太重了
【发布时间】:2016-07-07 05:45:39
【问题描述】:

我一直在使用 Angular 进行开发,但我刚开始使用 Angular 2,在完成 Angular 2 教程中的快速入门后,你考虑尝试在服务器中开发完成的应用程序,就像在生产模式下一样。

我没有使用 SystemJS 和 Gulp 的经验,所以我花了一段时间,但我终于设法让它工作了。现在我有两个问题:

对于一个 Hello World 应用程序,它真的很重,大约 20MB,因为我必须从 Angular 2 库中下载大量文件。我的猜测是我真的不需要这么多,但是虽然我只从 @angular/core 和 @angular/platform-b​​rowser-dynamic 开始,它们是我的应用程序 ts 文件中引用的那些,但 angular 在部署中不断抛出错误消息直到我包含了整个 @angular 库。

另一方面,当我运行应用程序时,我再次看到许多单个文件正在下载,这不是我的想法。必须有一种方法可以只下载一个包含所有库(一个包?)的单个(缩小)文件,但我不知道该怎么做。

谁能帮帮我?

这是我的主要配置文件。

system.config.js

(function(global) {

  // map tells the System loader where to look for things
  var map = {
    'app': 'app', // 'dist',
    '@angular': 'lib/@angular',
    'rxjs': 'lib/rxjs'
  };

  // packages tells the System loader how to load when no filename and/or no extension
  var packages = {
    'app': { main: 'main.js',  defaultExtension: 'js' },
    'rxjs': { defaultExtension: 'js' }
  };

  var ngPackageNames = [
    'common',
    'compiler',
    'core',
    'http',
    'platform-browser',
    'platform-browser-dynamic'
  ];
  // Individual files (~300 requests):
  function packIndex(pkgName) {
    packages['@angular/' + pkgName] = { main: 'index.js', defaultExtension: 'js' };
  }
  // Add package entries for angular packages
  ngPackageNames.forEach(packIndex);

  var config = {
    map: map,
    packages: packages
  };

  System.config(config);

})(this);

index.html

<html>
  <head>
    <title>Angular 2 QuickStart</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" type="image/x-icon" href="favicon.ico">
    <link rel="stylesheet" href="./css/styles.css">
    <!-- 1. Load libraries -->
     <!-- Polyfill(s) for older browsers -->
    <script src="lib/shim.min.js"></script>
    <script src="lib/zone.js"></script>
    <script src="lib/Reflect.js"></script>
    <script src="lib/system.src.js"></script>
    <!-- 2. Configure SystemJS -->
    <script src="systemjs.config.js"></script>
    <script>
      System.import('app').catch(function(err){ console.error(err); });
    </script>
  </head>
  <!-- 3. Display the application -->
  <body>
    <my-app>Loading...</my-app>
  </body>
</html>

gulpfile.js

var gulp = require('gulp');
var ts = require('gulp-typescript');
const babel = require('gulp-babel');

var tsProject = ts.createProject('tsconfig.json');

gulp.task('babel-dp', ['resources', 'babel']);
gulp.task('ts-dp', ['resources', 'ts']);

gulp.task('resources', () => {
  gulp.src([
    'node_modules/core-js/client/shim.min.js',
    'node_modules/zone.js/dist/zone.js',
    'node_modules/reflect-metadata/Reflect.js',
    'node_modules/systemjs/dist/system.src.js'
  ]).pipe(gulp.dest('web/lib'));

  gulp.src([
    'node_modules/@angular/**/*',
  ]).pipe(gulp.dest('web/lib/@angular'));

  gulp.src([
    'node_modules/rxjs/**/*',
  ]).pipe(gulp.dest('web/lib/rxjs'));

  gulp.src([
    'app/**/*.js'
  ]).pipe(gulp.dest('web/app'));

  gulp.src([
    'styles.css'
  ]).pipe(gulp.dest('web/css'));

  gulp.src([
    'index.html',
    'systemjs.config.js',
    'favicon.ico'
  ]).pipe(gulp.dest('web'));
});

gulp.task('babel', () => {
    return gulp.src([
    'app/**/*.ts'
    ])
        .pipe(babel({presets: ['es2015']}))
        .pipe(gulp.dest('web/js'));
});

gulp.task('ts', function(done) {
  var tsResult = tsProject.src([
      'app/**/*.ts'
    ])
    .pipe(ts(tsProject));
  return tsResult.js.pipe(gulp.dest('web/js'));
});

如果您需要任何其他文件,请告诉我。 非常感谢!

更新

我刚刚发现我可以使用 @angular 中的 umd.min.js 文件而不是单个 js 文件。这是从 20 到 5MB 的大小,但当 Angular 1 的缩小版本小于 1MB 时,看起来仍然很大。

另一方面,即使我使用了这些 umd.min.js 文件,chrome 在加载应用程序时仍然在下载单个文件。

更新 2

按照 cmets 中的建议,我设法使用 systemjs-builder 创建了一个单独的包文件。现在我有一个包含我所有应用程序代码的单个文件 bundle.app.js,我的 index.html 现在看起来像这样

<html>
  <head>
    <title>Angular 2 QuickStart</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" type="image/x-icon" href="favicon.ico">
    <link rel="stylesheet" href="css/styles.css">
    <!-- 1. Load libraries -->
    <script src="app/bundle.app.js"> </script>
    <!-- Polyfill(s) for older browsers -->
    <script src="node_modules/core-js/client/shim.min.js"></script>
    <script src="node_modules/zone.js/dist/zone.js"></script>
    <script src="node_modules/reflect-metadata/Reflect.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>
    <script>
      System.import('app').catch(function(err) { console.error(err); });
    </script>
  </head>
  <!-- 2. Display the application -->
  <body>
    <my-app>Loading...</my-app>
  </body>
</html>

但是现在 chrome 找不到 html 中导入的 js:shim.min.js、zone.js、Reflect.js 和 system.src.js。 我在 systemjs.config.js 中添加了一行以包含 node_modules 以防万一,但我认为没有必要。无论如何,它也不起作用。这些导入不应该已经包含在捆绑包中了吗?

【问题讨论】:

    标签: javascript angular gulp systemjs


    【解决方案1】:

    好的,我终于得到了一个有效的配置,所以我会在这里复制所有需要的文件,以防有人发现它有帮助。

    index.html

    <html>
      <head>
        <title>Angular 2 QuickStart Deploy</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="icon" type="image/x-icon" href="favicon.ico">
        <link rel="stylesheet" href="css/styles.css">
        <!-- 1. Load libraries -->
        <!-- Polyfill(s) for older browsers -->
        <script src="lib/shim.min.js"></script>
        <script src="lib/zone.js"></script>
        <script src="lib/Reflect.js"></script>
        <script src="lib/system.src.js"></script>
      </head>
      <!-- 2. Display the application -->
      <body>
        <my-app>Loading...</my-app>
        <!-- application bundle -->
        <script src="app/bundle.app.js"></script>
      </body>
    </html>
    

    gulpfile.js

    const gulp = require('gulp');
    const ts = require('gulp-typescript');
    const babel = require('gulp-babel');
    const Builder = require('systemjs-builder');
    
    // systemjs-builder
    const builder = new Builder('.', 'systemjs.config.js');
    
    // typescript transpiler
    var tsProject = ts.createProject('tsconfig.json');
    
    gulp.task('babel-dp', ['resources', 'babel']);
    gulp.task('ts-dp', ['resources', 'ts']);
    
    gulp.task('bundle:app', () => {
      builder.buildStatic('app/*.js', 'web/app/bundle.app.js')
      .then(function() {
        console.log('Build complete');
      })
      .catch(function(err) {
        console.log('error ' + err);
      })
    })
    
    gulp.task('resources', () => {
      gulp.src([
        'node_modules/core-js/client/shim.min.js',
        'node_modules/zone.js/dist/zone.js',
        'node_modules/reflect-metadata/Reflect.js',
        'node_modules/systemjs/dist/system.src.js'
      ]).pipe(gulp.dest('web/lib'));
    
      gulp.src([
        'styles.css'
      ]).pipe(gulp.dest('web/css'));
    
      gulp.src([
        'index.html',
        'favicon.ico'
      ]).pipe(gulp.dest('web'));
    });
    
    gulp.task('babel', () => {
        return gulp.src([
        'app/**/*.ts'
        ])
            .pipe(babel({presets: ['es2015']}))
            .pipe(gulp.dest('web/js'));
    });
    
    gulp.task('ts', function(done) {
      var tsResult = tsProject.src([
          'app/**/*.ts'
        ])
        .pipe(ts(tsProject));
      //return tsResult.js.pipe(gulp.dest('web/js'));
      return tsResult.js.pipe(gulp.dest('app/js'));
    });
    

    其余文件未更改。 对我来说,这里的要点是使用 systemjs-builder 创建包(感谢@Thorsten 的提示)以及在 index.html 中使用包。

    【讨论】:

      【解决方案2】:

      至于捆绑多个文件/单个文件中的库,您可以使用 gulp 任务。

      这里有一些东西可以帮助您入门。请务必了解不同线条的含义,可能会发生,您必须更改一些小部分以反映您的需求。

      const gulp = require('gulp');
      const path = require('path');
      const runSequence = require('run-sequence');
      const paths = require('../paths');
      
      gulp.task('bundle', cb => {
          runSequence(
              'bundle:app',
              'bundle:vendor',
              cb
          );
      });
      
      const app = 'app/**/*.js';
      const specs = 'app/**/*.spec.js';
      
      gulp.task('bundle:app', () => {
          const appModules = `[${app}] - [${specs}]`; // except specs
          return bundle(appModules, paths.dst + '/bundle.app.js', { baseUrl: paths.dst });
      });
      
      gulp.task('bundle:vendor', () => {
          // build app and remove the app code - this leaves only 3rd party dependencies
          const dstApp = path.join(paths.dst, app);
          const dstSpecs = path.join(paths.dst, specs);
          const vendorModules = `${dstApp} - [${dstApp}]`; 
      
          return bundle(vendorModules, paths.dst + '/bundle.vendor.js');
      });
      
      function bundle(src, dst, opt) {        
          const bundleOptions = Object.assign({
              baseUrl: '.',
              minify: false,
              sourceMaps: false,
              lowResSourceMaps: false, // mapping granularity is per-line instead of per-character
          }, opt);
      
          const Builder = require('systemjs-builder');
          const builder = new Builder(bundleOptions.baseUrl, paths.src + '/systemjs.config.js');
      
          return builder.bundle(src, dst, bundleOptions);
      }
      

      缩小是额外的步骤,但 gulp-minify 或 gulp-uglify 值得一看。

      【讨论】:

      • 嗨@Thorsten Viel,我设法使用您的gulpfile 的简化版本创建了一个包,但我在index.html 中的导入方面遇到了困难;即,我现在有这个 &lt;script src="node_modules/core-js/client/shim.min.js"&gt;&lt;/script&gt; 并且浏览器找不到它,它不应该已经包含在包中吗?
      • gulp 捆绑了 systemjs.config.js 中引用的内容。 Shim 通常不是其中的一部分。同样适用于区域或 polyfill,例如因此,在您的 index.html 中使用直接引用来表示未捆绑/打包的 js 是正确的。
      • 因为我还不能评论这个问题(低声望):“我刚刚发现我可以使用 @angular 中的 umd.min.js 文件而不是单个 js 文件。就是这样,从 20 到 5MB,但当 Angular 1 的缩小版小于 1MB 时,看起来仍然很多。”你在进口什么?你能分享你的systemjs.config.js吗?我的几个 Angular 和 3rd 方包的捆绑包只有 1.6MB。
      • 感谢您的回复。我的第一次更新没有使用捆绑包,我将 node_modules 中的 umd.min.js 文件复制到我的部署文件夹中。现在我的包只有大约 2K,这是正确的,因为它基本上是一个 Hello World 应用程序。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-22
      • 2016-07-17
      • 1970-01-01
      • 2016-03-27
      • 2019-06-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多