如何将Angular应用捆绑到生产环境中

把Angular(版本2、版本4、版本6……)捆绑到一个活跃的web服务器上进行生产的最佳方法是什么?

请在回答中包含Angular版本,以便我们在它转移到后续版本时更好地跟踪。

274939 次浏览

2.0.1 Final using Gulp (TypeScript - Target: ES5)


前设置

  • npm install(当目录是projectFolder时在cmd中运行)

捆绑销售的步骤

  • npm run bundle(当目录是projectFolder时在cmd中运行)

    bundle被生成到projectFolder / bundles / < /强> < / p >

输出

  • bundles/dependencies.bundle.js [大小:~ 1mb(尽可能小)]
    • 包含RXJS和angular依赖项,而不是整个框架
    • 李< / ul > < / >
    • bundles/app.bundle.js [大小:取决于你的项目, mine is ~ 0.5 MB]
      • 包含您的项目
      • 李< / ul > < / >

      文件结构

      • projectFolder / app /(所有组件、指令、模板等)
      • projectFolder / gulpfile.js

      var gulp = require('gulp'),
      tsc = require('gulp-typescript'),
      Builder = require('systemjs-builder'),
      inlineNg2Template = require('gulp-inline-ng2-template');
      
      
      gulp.task('bundle', ['bundle-app', 'bundle-dependencies'], function(){});
      
      
      gulp.task('inline-templates', function () {
      return gulp.src('app/**/*.ts')
      .pipe(inlineNg2Template({ useRelativePaths: true, indent: 0, removeLineBreaks: true}))
      .pipe(tsc({
      "target": "ES5",
      "module": "system",
      "moduleResolution": "node",
      "sourceMap": true,
      "emitDecoratorMetadata": true,
      "experimentalDecorators": true,
      "removeComments": true,
      "noImplicitAny": false
      }))
      .pipe(gulp.dest('dist/app'));
      });
      
      
      gulp.task('bundle-app', ['inline-templates'], function() {
      // optional constructor options
      // sets the baseURL and loads the configuration file
      var builder = new Builder('', 'dist-systemjs.config.js');
      
      
      return builder
      .bundle('dist/app/**/* - [@angular/**/*.js] - [rxjs/**/*.js]', 'bundles/app.bundle.js', { minify: true})
      .then(function() {
      console.log('Build complete');
      })
      .catch(function(err) {
      console.log('Build error');
      console.log(err);
      });
      });
      
      
      gulp.task('bundle-dependencies', ['inline-templates'], function() {
      // optional constructor options
      // sets the baseURL and loads the configuration file
      var builder = new Builder('', 'dist-systemjs.config.js');
      
      
      return builder
      .bundle('dist/app/**/*.js - [dist/app/**/*.js]', 'bundles/dependencies.bundle.js', { minify: true})
      .then(function() {
      console.log('Build complete');
      })
      .catch(function(err) {
      console.log('Build error');
      console.log(err);
      });
      });
      
      • projectFolder / package.json(与快速入门指南相同,只是显示了捆绑所需的devDependencies和npm脚本)

      {
      "name": "angular2-quickstart",
      "version": "1.0.0",
      "scripts": {
      ***
      "gulp": "gulp",
      "rimraf": "rimraf",
      "bundle": "gulp bundle",
      "postbundle": "rimraf dist"
      },
      "license": "ISC",
      "dependencies": {
      ***
      },
      "devDependencies": {
      "rimraf": "^2.5.2",
      "gulp": "^3.9.1",
      "gulp-typescript": "2.13.6",
      "gulp-inline-ng2-template": "2.0.1",
      "systemjs-builder": "^0.15.16"
      }
      }
      

      (function(global) {
      
      
      // map tells the System loader where to look for things
      var map = {
      'app':                        'app',
      'rxjs':                       'node_modules/rxjs',
      'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
      '@angular':                   'node_modules/@angular'
      };
      
      
      // packages tells the System loader how to load when no filename and/or no extension
      var packages = {
      'app':                        { main: 'app/boot.js',  defaultExtension: 'js' },
      'rxjs':                       { defaultExtension: 'js' },
      'angular2-in-memory-web-api': { defaultExtension: 'js' }
      };
      
      
      var packageNames = [
      '@angular/common',
      '@angular/compiler',
      '@angular/core',
      '@angular/forms',
      '@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 = {
      map: map,
      packages: packages
      };
      
      
      // filterSystemConfig - index.asp's chance to modify config before we register it.
      if (global.filterSystemConfig) { global.filterSystemConfig(config); }
      
      
      System.config(config);
      
      
      })(this);
      
      • projetcFolder / dist-systemjs.config.js(刚刚显示了与systemjs.config.json的区别)

      var map = {
      'app':                        'dist/app',
      };
      
      • projectFolder / index.html(生产)- 脚本标记的顺序非常关键。将__ABC0标记放在bundle标记之后仍然允许程序运行,但依赖包将被忽略,依赖项将从node_modules文件夹加载。

      <!doctype html>
      <html lang="en">
      <head>
      <meta charset="utf-8"/>
      <meta name="viewport" content="width=device-width, initial-scale=1"/>
      <base href="/"/>
      <title>Angular</title>
      <link rel="stylesheet" type="text/css" href="style.css"/>
      </head>
      <body>
      
      
      <my-app>
      loading...
      </my-app>
      
      
      <!-- Polyfill(s) for older browsers -->
      <script src="node_modules/core-js/client/shim.min.js"></script>
      
      
      <script src="node_modules/zone.js/dist/zone.min.js"></script>
      <script src="node_modules/reflect-metadata/Reflect.js"></script>
      <script src="node_modules/systemjs/dist/system.js"></script>
      
      
      <script src="dist-systemjs.config.js"></script>
      <!-- Project Bundles. Note that these have to be loaded AFTER the systemjs.config script -->
      <script src="bundles/dependencies.bundle.js"></script>
      <script src="bundles/app.bundle.js"></script>
      
      
      <script>
      System.import('app/boot').catch(function (err) {
      console.error(err);
      });
      </script>
      </body>
      </html>
      
      • projectFolder / app / boot.ts是引导程序所在的位置。

      这是我能做的最好的:)

2 to 14 (TypeScript)使用Angular CLI

前设置

  • npm install -g @angular/cli
  • ng new projectFolder创建一个新的应用程序

捆绑销售的步骤

  • ng build(当目录为projectFolder时在命令行中运行)。

    flag prod bundle for production现在是默认值(参见Angular文档,如果需要可以自定义它)。

  • 使用下面的命令使用Brotli压缩压缩资源

    for i in dist/*/*; do brotli $i; done

v6+的包默认生成到projectFolder/dist(/$projectFolder) * *

输出

Angular 14.0.2 with CLI 14.0.2and option CSS without Angular routing

  • dist/main.[hash].js你绑定的应用程序[size: 118 KB for new Angular CLI application empty, 36个KB compressed]。
  • dist/polyfill-[es-version].[hash].bundle.js绑定的polyfill依赖项(@angular, RxJS…)[size: 34kb for new Angular CLI application empty, 11 KB compressed]。
  • 应用程序的dist/index.html入口点。
  • dist/runtime.[hash].bundle.js webpack加载器
  • dist/style.[hash].bundle.css样式定义
  • 从Angular CLI资产配置中复制的dist/assets资源

部署

您可以使用启动本地HTTP服务器的ng serve --prod命令获取应用程序的预览,以便使用http://localhost:4200访问具有生产文件的应用程序。这在生产中使用并不安全。

对于生产应用,您必须从您选择的HTTP服务器中的dist文件夹中部署所有文件。

使用SystemJs生成器和gulp的Angular 2生产工作流

角。IO有快速入门教程。我复制了本教程,并扩展了一些简单的gulp任务,将所有内容捆绑到dist文件夹,可以复制到服务器并像那样工作。我尝试优化所有内容,以便在Jenkis CI上正常工作,因此node_modules可以被缓存,不需要复制。

Github上的示例应用程序的源代码:https://github.com/Anjmao/angular2-production-workflow

生产步骤
  1. 清洁打字文件编译js文件和dist文件夹
  2. 在app文件夹内编译typescript文件
  3. 使用SystemJs捆绑器将所有内容捆绑到dist文件夹,并生成哈希值,以便浏览器缓存刷新
  4. 使用gulp-html-replace将index.html脚本替换为捆绑版本并复制到dist文件夹
  5. 复制资产文件夹内的所有内容到dist文件夹

节点:虽然你总是可以创建自己的构建过程,但我强烈建议使用angular-cli,因为它有所有需要的工作流,现在它工作得很完美。我们已经在生产环境中使用它了,在使用angular-cli时没有任何问题。

Angular CLI 1.x。适用于Angular 4.x。x 5. x.x)

这支持:

  • 角2。X和4.x
  • 最新Webpack 2.x
  • Angular AoT编译器
  • 路由(正常和惰性)
  • SCSS
  • 自定义文件捆绑(资产)
  • 附加开发工具(linter, unit &端到端测试设置)

初始设置

ng new project-name --routing

你可以添加--style=scss来支持SASS .scss。

你可以添加--ng4来使用Angular 4而不是Angular 2。

创建项目后,CLI会自动为你运行npm install。如果你想使用Yarn,或者只是想在没有安装的情况下查看项目框架,看看怎么做

包的步骤

在项目文件夹内:

ng build -prod

在当前版本中,您需要手动指定--aot,因为它可以在开发模式中使用(尽管由于速度较慢,这是不实际的)。

它还为更小的bundle执行AoT编译(没有Angular编译器,而是生成编译器输出)。如果你使用Angular 4, AoT的包会小得多,因为生成的代码更小 你可以通过运行ng build --aot来测试你的应用程序在开发模式下的AoT (sourcemaps, no minification)和AoT

输出

默认的输出目录是./dist,尽管它可以在./angular-cli.json中更改。

部署文件

构建步骤的结果如下:

(注意:<content-hash>指的是文件内容的散列/指纹,这意味着一种缓存破坏方式,这是可能的,因为Webpack自己写入script标记)

    <李> ./dist/assets < br > 原样从./src/assets/**复制的文件 <李> ./dist/index.html < br > 从./src/index.html,添加webpack脚本后,它
    源模板文件可在./angular-cli.json中配置 <李> ./dist/inline.js < br > 小型webpack加载器/ polyfill <李> ./dist/main.<content-hash>.bundle.js < br > 主.js文件包含所有生成/导入的.js脚本 <李> ./dist/styles.<content-hash>.bundle.js < br > 当你使用Webpack加载器的CSS,这是CLI的方式,他们是通过JS加载这里

在旧版本中,它还创建了gzip版本来检查它们的大小,以及.map sourcemaps文件,但这不再发生,因为人们一直要求删除这些文件。

其他文件

在某些情况下,你可能会发现其他不需要的文件/文件夹:

    <李> ./out-tsc/ < br > 从./src/tsconfig.jsonoutDir <李> ./out-tsc-e2e/ < br > 从./e2e/tsconfig.jsonoutDir <李> ./dist/ngfactory/ < br > 来自AoT编译器(在beta 16中不能在没有分叉CLI的情况下进行配置)

带Webpack的Angular 2(不需要CLI设置)

1- Angular2团队的教程

Angular2团队发布了一个用于使用Webpack的教程

我在一个小GitHub种子项目中创建并放置了教程中的文件。因此,您可以快速地尝试工作流。

指令:

  • < >强npm安装< / >强

  • < >强npm开始> < /强。为发展。这将创建一个虚拟“dist”文件夹,该文件夹将被重载到您的本地主机地址。

  • <李> < p > NPM运行构建。用于生产。这将创建一个可以发送到web服务器的物理“dist”文件夹版本。dist文件夹有7.8MB,但实际上只需要234KB就可以在web浏览器中加载页面。
    < br > < / p >

2 - Webkit入门套件

这个Webpack入门套件提供了比上面教程更多的测试功能,看起来相当受欢迎。

        **Production build with


- Angular Rc5
- Gulp
- typescripts
- systemjs**


1)con-cat all js files  and css files include on index.html using  "gulp-concat".
- styles.css (all css concat in this files)
- shims.js(all js concat in this files)


2)copy all images and fonts as well as html files  with gulp task to "/dist".


3)Bundling -minify angular libraries and app components mentioned in systemjs.config.js file.
Using gulp  'systemjs-builder'


SystemBuilder = require('systemjs-builder'),
gulp.task('system-build', ['tsc'], function () {
var builder = new SystemBuilder();
return builder.loadConfig('systemjs.config.js')
.then(function () {
builder.buildStatic('assets', 'dist/app/app_libs_bundle.js')
})
.then(function () {
del('temp')
})
});




4)Minify bundles  using 'gulp-uglify'


jsMinify = require('gulp-uglify'),


gulp.task('minify', function () {
var options = {
mangle: false
};
var js = gulp.src('dist/app/shims.js')
.pipe(jsMinify())
.pipe(gulp.dest('dist/app/'));
var js1 = gulp.src('dist/app/app_libs_bundle.js')
.pipe(jsMinify(options))
.pipe(gulp.dest('dist/app/'));
var css = gulp.src('dist/css/styles.min.css');
return merge(js,js1, css);
});


5) In index.html for production


<html>
<head>
<title>Hello</title>


<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8" />


<link rel="stylesheet" href="app/css/styles.min.css" />
<script type="text/javascript" src="app/shims.js"></script>
<base href="/">
</head>
<body>
<my-app>Loading...</my-app>
<script type="text/javascript" src="app/app_libs_bundle.js"></script>
</body>


</html>


6) Now just copy your dist folder to '/www' in wamp server node need to copy node_modules in www.

直到今天,我仍然认为Ahead-of-Time Compilation烹饪书是产品捆绑的最佳食谱。你可以在这里找到它:https://angular.io/docs/ts/latest/cookbook/aot-compiler.html

到目前为止,我使用Angular 2的经验是,AoT创建了最小的构建,几乎没有加载时间。最重要的是,您只需要将几个文件交付到生产环境中。

这似乎是因为Angular编译器不会随产品版本一起发布,因为模板是“提前”编译的。看到你的HTML模板标记转换成javascript指令也很酷,这将很难反向工程到原始HTML。

我做了一个简单的视频,演示了Angular 2应用在开发阶段和AoT构建阶段的下载大小、文件数量等——你可以在这里看到:

< a href = " https://youtu。是/ ZoZDCgQwnmQ noreferrer“rel = > https://youtu.be/ZoZDCgQwnmQ < / >

你可以在这里找到视频中使用的源代码:

https://github.com/fintechneo/angular2-templates

“最佳”取决于场景。有时你只关心最小的单个包,但在大型应用程序中,你可能不得不考虑延迟加载。在某种程度上,将整个应用程序作为一个单一的bundle提供是不切实际的。

在后一种情况下,Webpack通常是最好的方法,因为它支持代码分割。

对于单个包,我会考虑Rollup,或者Closure编译器,如果你有勇气的话:-)

我已经创建了我在这里使用过的所有Angular捆绑器的示例:http://www.syntaxsuccess.com/viewarticle/angular-production-builds

代码可以在这里找到:https://github.com/thelgevold/angular-2-samples

Angular版本:4.1.x

你可以在github上使用 angular-cli-ghpages < / p >

请查看链接,以了解如何使用此cli进行部署。

部署的网站通常存储在github中的某个分支中

gh-pages

使用可以克隆git分支和使用它像静态网站在您的服务器

只要在一分钟内用webpack 3安装angular 4,你的开发和生产ENV包就会准备好,没有任何问题 只要按照下面的github doc

https://github.com/roshan3133/angular2-webpack-starter

请在当前项目目录下尝试以下CLI命令。它将创建dist文件夹bundle。因此,您可以上传dist文件夹中的所有文件进行部署。

Ng build——prod——aot——base-href。

Ng服务的工作是为我们的应用程序的开发目的服务。生产方面呢?如果我们看看我们的包装。Json文件,我们可以看到有我们可以使用的脚本:

"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build --prod",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},

构建脚本使用Angular CLI的ng build,并带有——prod标志。我们现在试试。我们有两种方法:

#使用NPM脚本

npm run build

#直接使用cli

ng build --prod

这次我们得到了四个文件而不是五个。——prod标志告诉Angular把我们的应用缩小很多。

ng build—配置生产 (角14起)