我如何实际部署Angular 2 + Typescript + systemjs应用程序?

时间:2016-03-29 13:01:34

标签: typescript angular systemjs

在angular.io上有一个快速入门的教程,它使用的是typescript& amp; systemjs。 现在我已经运行了miniapp,我将如何创建可部署的东西?我无法找到任何关于它的信息。

我是否需要任何额外的工具,System.config中的任何其他设置?

(我知道我可以使用webpack&创建一个bundle.js,但我想在教程中使用systemjs)

有人可以通过此设置(Angular 2,TypeScript,systemjs)共享他们的构建过程

7 个答案:

答案 0 :(得分:66)

在这个级别要理解的关键是使用以下配置,你不能直接连接编译的JS文件。

在TypeScript编译器配置中:

{
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "declaration": false,
    "stripInternal": true,
    "module": "system",
    "moduleResolution": "node",
    "noEmitOnError": false,
    "rootDir": ".",
    "inlineSourceMap": true,
    "inlineSources": true,
    "target": "es5"
  },
  "exclude": [
    "node_modules"
  ]
}

在HTML

System.config({
  packages: {
    app: {
      defaultExtension: 'js',
      format: 'register'
    }
  }
});

事实上,这些JS文件将包含匿名模块。匿名模块是一个使用System.register但没有模块名称作为第一个参数的JS文件。当systemjs配置为模块管理器时,这就是typescript编译器默认生成的内容。

因此,要将所有模块放入单个JS文件中,您需要利用TypeScript编译器配置中的outFile属性。

您可以在gulp中使用以下内容来执行此操作:

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

var tsProject = ts.createProject('tsconfig.json', {
  typescript: require('typescript'),
  outFile: 'app.js'
});

gulp.task('tscompile', function () {
  var tsResult = gulp.src('./app/**/*.ts')
                     .pipe(ts(tsProject));

  return tsResult.js.pipe(gulp.dest('./dist'));
});

这可以与其他一些处理相结合:

  • 对已编译的TypeScript文件进行uglify
  • 创建app.js文件
  • 为第三方库创建vendor.js文件
  • 创建boot.js文件以导入引导应用程序的模块。此文件必须包含在页面末尾(加载所有页面时)。
  • 更新index.html以考虑这两个文件

在gulp任务中使用以下依赖项:

  • 吞-的concat
  • 吞-HTML替换
  • 吞-打字稿
  • 吞掉-丑化

以下是一个示例,因此可以进行调整。

  • 创建app.min.js文件

    gulp.task('app-bundle', function () {
      var tsProject = ts.createProject('tsconfig.json', {
        typescript: require('typescript'),
        outFile: 'app.js'
      });
    
      var tsResult = gulp.src('app/**/*.ts')
                       .pipe(ts(tsProject));
    
      return tsResult.js.pipe(concat('app.min.js'))
                    .pipe(uglify())
                    .pipe(gulp.dest('./dist'));
    });
    
  • 创建vendors.min.js文件

    gulp.task('vendor-bundle', function() {
      gulp.src([
        'node_modules/es6-shim/es6-shim.min.js',
        'node_modules/systemjs/dist/system-polyfills.js',
        '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/http.dev.js'
      ])
      .pipe(concat('vendors.min.js'))
      .pipe(uglify())
      .pipe(gulp.dest('./dist'));
    });
    
  • 创建boot.min.js文件

    gulp.task('boot-bundle', function() {
      gulp.src('config.prod.js')
        .pipe(concat('boot.min.js'))
        .pipe(uglify())
        .pipe(gulp.dest('./dist'));
     });
    

    config.prod.js只包含以下内容:

     System.import('boot')
        .then(null, console.error.bind(console));
    
  • 更新index.html文件

    gulp.task('html', function() {
      gulp.src('index.html')
        .pipe(htmlreplace({
          'vendor': 'vendors.min.js',
          'app': 'app.min.js',
          'boot': 'boot.min.js'
        }))
        .pipe(gulp.dest('dist'));
    });
    

    index.html如下所示:

    <html>
      <head>
        <!-- Some CSS -->
    
        <!-- build:vendor -->
        <script src="node_modules/es6-shim/es6-shim.min.js"></script>
        <script src="node_modules/systemjs/dist/system-polyfills.js"></script>
        <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
        <script src="node_modules/systemjs/dist/system.src.js"></script>
        <script src="node_modules/rxjs/bundles/Rx.js"></script>
        <script src="node_modules/angular2/bundles/angular2.dev.js"></script>
        <script src="node_modules/angular2/bundles/http.dev.js"></script>
        <!-- endbuild -->
    
        <!-- build:app -->
        <script src="config.js"></script>
        <!-- endbuild -->
      </head>
    
      <body>
        <my-app>Loading...</my-app>
    
        <!-- build:boot -->
        <!-- endbuild -->
      </body>
    </html>
    

请注意,System.import('boot');必须在正文末尾完成,以等待从app.min.js文件注册所有应用组件。

我这里没有描述处理CSS和HTML缩小的方法。

答案 1 :(得分:28)

您可以使用angular2-cli构建命令

ng build -prod

https://github.com/angular/angular-cli/wiki/build#bundling

  

使用 -prod 标记通过ng build -prodng serve -prod将所有依赖项捆绑到单个文件中构建,并使用树木震动技术。

更新

当angular2在rc4

时提交了这个答案

我曾经在angular-cli beta21和angular2 ^ 2.1.0上再次尝试过它并且按预期工作

此答案需要使用angular-cli初始化应用程序 你可以用

ng new myApp

或现有的

ng init

更新08/06/2018

对于角度6,语法不同。

ng build --prod --build-optimizer

检查documentation

答案 2 :(得分:12)

您可以使用带有GulpSystemJS-Builder的SystemJS在Typescript中构建Angular 2(2.0.0-rc.1)项目。

以下是如何构建,捆绑和缩小运行2.0.0-rc.1(full sourcelive example)的英雄之旅的简化版本。

<强> gulpfile.js

&#13;
&#13;
var gulp = require('gulp');
var sourcemaps = require('gulp-sourcemaps');
var concat = require('gulp-concat');
var typescript = require('gulp-typescript');
var systemjsBuilder = require('systemjs-builder');

// Compile TypeScript app to JS
gulp.task('compile:ts', function () {
  return gulp
    .src([
        "src/**/*.ts",
        "typings/*.d.ts"
    ])
    .pipe(sourcemaps.init())
    .pipe(typescript({
        "module": "system",
        "moduleResolution": "node",
        "outDir": "app",
        "target": "ES5"
    }))
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('app'));
});

// Generate systemjs-based bundle (app/app.js)
gulp.task('bundle:app', function() {
  var builder = new systemjsBuilder('public', './system.config.js');
  return builder.buildStatic('app', 'app/app.js');
});

// Copy and bundle dependencies into one file (vendor/vendors.js)
// system.config.js can also bundled for convenience
gulp.task('bundle:vendor', function () {
    return gulp.src([
        'node_modules/jquery/dist/jquery.min.js',
        'node_modules/bootstrap/dist/js/bootstrap.min.js',
        'node_modules/es6-shim/es6-shim.min.js',
        'node_modules/es6-promise/dist/es6-promise.min.js',
        'node_modules/zone.js/dist/zone.js',
        'node_modules/reflect-metadata/Reflect.js',
        'node_modules/systemjs/dist/system-polyfills.js',
        'node_modules/systemjs/dist/system.src.js',
      ])
        .pipe(concat('vendors.js'))
        .pipe(gulp.dest('vendor'));
});

// Copy dependencies loaded through SystemJS into dir from node_modules
gulp.task('copy:vendor', function () {
  gulp.src(['node_modules/rxjs/**/*'])
    .pipe(gulp.dest('public/lib/js/rxjs'));

  gulp.src(['node_modules/angular2-in-memory-web-api/**/*'])
    .pipe(gulp.dest('public/lib/js/angular2-in-memory-web-api'));
  
  return gulp.src(['node_modules/@angular/**/*'])
    .pipe(gulp.dest('public/lib/js/@angular'));
});

gulp.task('vendor', ['bundle:vendor', 'copy:vendor']);
gulp.task('app', ['compile:ts', 'bundle:app']);

// Bundle dependencies and app into one file (app.bundle.js)
gulp.task('bundle', ['vendor', 'app'], function () {
    return gulp.src([
        'app/app.js',
        'vendor/vendors.js'
        ])
    .pipe(concat('app.bundle.js'))
    .pipe(uglify())
    .pipe(gulp.dest('./app'));
});

gulp.task('default', ['bundle']);
&#13;
&#13;
&#13;

<强> system.config.js

&#13;
&#13;
var map = {
  'app':                                'app',
  'rxjs':                               'vendor/rxjs',
  'zonejs':                             'vendor/zone.js',
  'reflect-metadata':                   'vendor/reflect-metadata',
  '@angular':                           'vendor/@angular'
};

var packages = {
  'app':                                { main: 'main', defaultExtension: 'js' },
  'rxjs':                               { defaultExtension: 'js' },
  'zonejs':                             { main: 'zone', defaultExtension: 'js' },
  'reflect-metadata':                   { main: 'Reflect', 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',
];

packageNames.forEach(function(pkgName) {
  packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
});

System.config({
  map: map,
  packages: packages
});
&#13;
&#13;
&#13;

答案 3 :(得分:1)

这是我对Angular 2的MEA2N样板:https://github.com/simonxca/mean2-boilerplate

它是一个简单的样板,使用tsc将事物放在一起。 (实际上使用grunt-ts,其核心只是tsc命令。)没有必要的Wekpack等。

无论你是否使用grunt,我的想法是:

  • 将您的应用编写在名为ts/的文件夹中(例如:public/ts/
  • 使用tscts/文件夹的目录结构镜像到js/文件夹,只引用js/index.html文件夹中的文件。

要让 grunt-ts 工作(应该有一个与plain tsc,Gulp等等的命令),你的tsconfig.json中有一个名为{{1}的属性},并在"outDir": "../js"中使用:

引用它
gruntfile.js

然后运行grunt.initConfig({ ts: { source: {tsconfig: 'app/ts/tsconfig.json'} }, ... }); ,这会将您的应用转移到grunt ts并将其镜像到public/ts/

有。超级简单易懂。不是最好的方法,但是一个很好的方法。

答案 4 :(得分:1)

我发现为systemJs捆绑角度rc1的最简单方法是使用gulpsystemjs-builder

gulp.task('bundle', function () {
    var path = require('path');
    var Builder = require('systemjs-builder');

    var builder = new Builder('/node_modules');

    return builder.bundle([
        '@angular/**/*.js'
        ], 
        'wwwroot/bundle.js', 
        { minify: false, sourceMaps: false })
        .then(function () {
            console.log('Build complete');
        })
        .catch(function (err) {
            console.log('Build error');
            console.log(err);
        });
});

正如评论中所指出的,当使用moduleId: module.id

捆绑组件时,systemJs目前存在问题

https://github.com/angular/angular/issues/6131

目前的建议(角度2 rc1)似乎是使用显式路径,即moduleId: '/app/path/'

答案 5 :(得分:0)

我在后端使用了expressjs来为我的ng2项目提供服务。你可以从我的github页面查看它: https://github.com/echonax/ng2-beta-and-test-framework

答案 6 :(得分:0)

在Angular.io网站下的“高级/部署”部分,建议最简单的部署方法是将开发环境复制到服务器中。

  1. 查看以下部分:最简单的部署。最终的项目文件显示在代码部分中。请注意,它已设置代码以从Web加载npm包文件(而不是从本地npm_modules文件夹加载)。

  2. 确保它在您的本地计算机上运行(npm start)。然后在项目文件夹下,复制&#39; / src&#39;子文件夹到您已设置的S3存储桶。您可以使用拖放功能进行复制,在此过程中,您可以选择选择文件的权限设置,确保将其设置为可读&#39;到每个人&#39;

  3. 在桶&#39;属性&#39;标签,寻找&#39;静态网站托管&#39;面板,检查&#39;使用此存储桶托管网站&#39;选项,并指定&#39; index.html&#39;索引文档和错误文档。

  4. 点击静态网站Endpoint,您的项目正在运行!