Angular2、Gulp、SystemJS -> 默认扩展问题

标签 angular gulp systemjs

我将 Angular2 与 SystemJS 一起使用,它在开发过程中运行良好。现在我想使用 gulp 部署我的第一个编译版本。

为了澄清,我使用了以下 systemJS 文件:

(function(global) {

  // map tells the System loader where to look for things
  var map = {
    'app':                            'app', // 'dist',
    'rxjs':                       'lib/node_modules/rxjs',
    'angular2-in-memory-web-api': 'lib/node_modules/angular2-in-memory-web-api',
    '@angular':                   'lib/node_modules/@angular',
    'ng2-charts/bundles':         'lib/node_modules/ng2-charts/bundles',
    'ng2-charts/components':      'lib/node_modules/ng2-charts/components',
    'ng2-cookies':                'lib/node_modules/ng2-cookies/'
  };

  // packages tells the System loader how to load when no filename and/or no extension
  var packages = {
    'app':                            { format: 'register', defaultExtension: 'js' },
    'rxjs':                       { defaultExtension: 'js' },
    'angular2-in-memory-web-api': { defaultExtension: 'js' }
  };

  var packageNames = [
    '@angular/common',
    '@angular/compiler',
    '@angular/core',
    '@angular/http',
    '@angular/platform-browser',
    '@angular/platform-browser-dynamic',
    '@angular/router',
    '@angular/router-deprecated',
    '@angular/testing',
    '@angular/upgrade',
  ];

  // add package entries for angular packages in the form '@angular/common': { main: 'index.js', defaultExtension: 'js' }
  packageNames.forEach(function(pkgName) {
    packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
  });

  var config = {
    baseURL: "/",
    defaultJSExtension : true,
    map: map,
    packages: packages
  }

  // filterSystemConfig - index.html's chance to modify config before we register it.
  if (global.filterSystemConfig) { global.filterSystemConfig(config); }

  System.config(config);

})(this);

以及以下 gulpfile:

const gulp = require('gulp');
const del = require('del');
const typescript = require('gulp-typescript');
const tscConfig = require('./tsconfig.json');
const tsconfig = require('tsconfig-glob');
const sourcemaps = require('gulp-sourcemaps');

// clean the contents of the distribution directory
gulp.task('clean', function () {
  return del('dist/**/*');
});

// TypeScript compile
gulp.task('compile', ['clean'], function () {
  return gulp
    .src(tscConfig.files)
    .pipe(sourcemaps.init())          // <--- sourcemaps
    .pipe(typescript(tscConfig.compilerOptions))
    .pipe(sourcemaps.write('.'))      // <--- sourcemaps
    .pipe(gulp.dest('dist'));
});

// copy dependencies
gulp.task('copy:libs', ['clean'], function() {
  return gulp.src([
      'node_modules/angular2/bundles/angular2-polyfills.js',
      'node_modules/systemjs/dist/system.src.js',
      'node_modules/rxjs/bundles/Rx.js',
      'node_modules/angular2/bundles/angular2.dev.js',
      'node_modules/angular2/bundles/router.dev.js',
      'node_modules/chart.js/dist/Chart.bundle.min.js',
      'node_modules/es6-shim/es6-shim.min.js',
      'node_modules/zone.js/dist/zone.js',
      'node_modules/reflect-metadata/Reflect.js',
      'node_modules/systemjs/dist/system.src.js',
      'TcAdsWebService.js'
    ])
    .pipe(gulp.dest('dist/lib'))
});

gulp.task('copy:modules',['clean'],function() {
  return gulp.src([
    './node_modules/@angular/**/*',
    './node_modules/rxjs/**/**',
    './node_modules/angular2-in-memory-web-api/**/*',
    './node_modules/ng2-charts/**/*',
    './node_modules/ng2-cookies/**/*'
  ],{base:'./'}).pipe(gulp.dest('dist/lib'));
});

gulp.task('copy:pics',['clean'], function () {
  return gulp.src(['pics/**/*'],{base:'./'}).pipe(gulp.dest('dist/css'));
})

gulp.task('copy:css',['clean'],function() {
  return gulp.src(['css/**/*'],{base:'./'}).pipe(gulp.dest('dist/css'));
});

gulp.task('copy:js',['clean'],function() {
  return gulp.src(['js/**/*'],{base:'./'}).pipe(gulp.dest('dist/js'));
});


gulp.task('copy:systemJS',['clean'],function() {
  return gulp.src(['systemjs.config.js']).pipe(gulp.dest('dist'));
});


// copy static assets - i.e. non TypeScript compiled source
gulp.task('copy:assets', ['clean'], function() {
  return gulp.src(['app/**/*', 'index.html', 'styles.css', '!app/**/*.ts'], { base : './' })
    .pipe(gulp.dest('dist'))
});

gulp.task('tsconfig-glob', function () {
  return tsconfig({
    configPath: '.',
    indent: 2
  });
});

gulp.task('build', ['tsconfig-glob','compile', 'copy:pics', 'copy:js', 'copy:css', 'copy:systemJS','copy:modules','copy:libs', 'copy:assets']);
gulp.task('default', ['build']);

构建 angular2 应用程序并将其加载到浏览器后,我在控制台中收到以下错误:

Unable to load script http://localhost:81/app/app.component

这表明它缺少编译文件中的 .js 扩展名。我很确定,那

'app':                            { format: 'register', defaultExtension: 'js' },

实际上应该要求编译器注意 app 文件夹中的 .js 扩展名,但事实并非如此。 这是我的第一个 angular2 项目和我的第一个 gulp 编译,我很确定我遗漏了它的一些基本方面,但我在我的代码中找不到它。

最佳答案

根据您的设置,您应该使用 systemjs-builder捆绑您的应用程序以进行生产。它接受您的 SystemJS 配置,因此不需要进一步配置。它将您的模块捆绑到一个文件中,并带有缩小、破坏等选项。

这是以“es6 模块”的方式做事,更好地利用我们的模块加载器,而不是像我们在传统的 javascript 应用程序 (es5) 中那样复制/粘贴模块。

这样做,我们可以将动态加载从索引页面中取出,只使用指向包的脚本标记,它应该会大大加快加载时间并最大限度地减少用户加载页面所需的下载内容。也不需要复制 node_modules。

给定一个文件夹结构:

src
|-- app
|   |-- main.ts
|   |-- index.html
|   |-- bundle.min.js
|-- system.config.js
|-- node_modules
|-- tsconfig.json

您甚至可以通过一个 gulp 任务完成所有这些。

任务:(需要 yargs):

var SystemBuilder = require('systemjs-builder');
var argv = require('yargs').argv;
var builder = new SystemBuilder();

gulp.task('bundle', function () {
    builder.loadConfig('./system.config.js')
        .then(function () {
            var outputFile = argv.prod ? './src/app/bundle.min.js' : './src/app/bundle.js';
            return builder.buildStatic('app', outputFile, {
                minify: argv.prod,
                mangle: argv.prod,
                rollup: argv.prod
            });
        })
        .then(function () {
            console.log('bundle built successfully!');
        });
});

运行这个任务:

gulp bundle

gulp bundle --prod

index.html:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
  <base href="/" />
  <title>Your App</title>

  <link rel="stylesheet" href='styles/bootstrap.min.css' />
  <script src="/bundle.js"></script>
</head>

<body>
  <your-root-component>
  </your-root-component>
</body>

</html>

系统.config.js:

(function (global) {

  var config = {
    compiler: "typescript",
    map: {
      'jquery': 'node_modules/jquery/dist',
      'bootstrap': 'node_modules/bootstrap/dist/js',
      "reflect-metadata": "node_modules/reflect-metadata",
      "zone": "node_modules/zone.js/dist",
      "crypto": "node_modules/crypto",
      'rxjs': 'node_modules/rxjs',
      'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
      '@angular': 'node_modules/@angular',
      'moment': 'node_modules/moment',
      'angular2-moment': 'node_modules/angular2-moment',
      'app': 'src/app',
    },
    meta: {
      'node_modules/bootstrap/dist/js/bootstrap.js': {
        format: 'global',
        deps: ['jquery']
      }
    },
    packages: {
      'jquery': { main: 'jquery.js', defaultExtension: 'js' },
      'bootstrap': { main: 'bootstrap.js', defaultExtension: 'js' },
      'zone': { main: 'zone.js', defaultExtension: 'js' },
      'reflect-metadata': { main: 'Reflect.js', defaultExtension: 'js' },
      'crypto': { main: 'sha1.js', defaultExtension: 'js' },
      'rxjs': { main: 'Rx.js', defaultExtension: 'js' },
      'moment':{main: 'moment.js', defaultExtension: 'js'},
      'angular2-moment': { main: 'index.js', defaultExtension: 'js' },
      'app': { main: 'main.js', defaultExtension: 'js' },

      '@angular/common': { main: 'index.js', defaultExtension: 'js' },
      '@angular/compiler': { main: 'index.js', defaultExtension: 'js' },
      '@angular/core': { main: 'index.js', defaultExtension: 'js' },
      '@angular/http': { main: 'index.js', defaultExtension: 'js' },
      '@angular/platform-browser': { main: 'index.js', defaultExtension: 'js' },
      '@angular/platform-browser-dynamic': { main: 'index.js', defaultExtension: 'js' },
      '@angular/router': { main: 'index.js', defaultExtension: 'js' },
      '@angular/testing': { main: 'index.js', defaultExtension: 'js' },
      '@angular/upgrade': { main: 'index.js', defaultExtension: 'js' },
      '@angular/forms': { main: 'index.js', defaultExtension: 'js' },
    }
  }

  System.config(config);

})(this);

综上所述:我相信您的包裹部分:

  var packages = {
    'app':                            { format: 'register', defaultExtension: 'js' },
    'rxjs':                       { defaultExtension: 'js' },
    'angular2-in-memory-web-api': { defaultExtension: 'js' }
  };

应该是:

  var packages = {
    'app':                            { main: 'main.js', defaultExtension: 'js' },
    'rxjs':                       { main: 'Rx.js', defaultExtension: 'js' },
    'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' }
  };

main.js 是任何包含 angular2 引导函数的文件。

关于Angular2、Gulp、SystemJS -> 默认扩展问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38203693/

相关文章:

javascript - 如何使 FileReader 与 Angular2 一起工作?

javascript - 将 gulp.start 函数迁移到 Gulp v4

javascript - 从 Angular 4 向 Express 发送删除请求中的数组

angular - ionic 视频静音属性被忽略

angular - 带有 Angular 的 MdBootstrap

javascript - SystemJS 对不存在的文件发出约 200 个请求

angular - 如何使用 Angular CLI 实现 ng2-ui(NPM 包)?

javascript - gulp-uglify 缩小不应该的脚本

javascript - gulp-ruby-sass 的语法错误似乎不正确

angular - 在 angular 4.4 应用程序中获取并加载远程组件/模块