如何捆绑Angular应用以进行制作

时间:2016-06-04 13:59:47

标签: angular webpack systemjs angular-cli

我想在这个帖子中跟踪和更新最新的(并且希望是最简单的)方法来捆绑Angular(版本2,4,...)以便在实时Web服务器上进行生产。

请在答案中包含Angular版本,以便我们可以更好地跟踪它何时转移到更高版本。

12 个答案:

答案 0 :(得分:330)

带有Angular CLI的

2.x, 4.x, 5.x, 6.x, 7.x, 8.x(TypeScript)

OneTime设置

  • npm install -g @angular/cli
  • ng new projectFolder创建新应用

捆绑步骤

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

    用于生产的

    标记prod包(请参阅Angular documentation以获取生产标记中包含的选项列表。)

  • 使用以下命令使用Brotli compression资源进行压缩

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

捆绑包默认生成 projectFolder / dist(/ $ projectFolder for 6)

输出

使用带有8.0.0-rc.2的Angular 8.0.0-rc.2和没有Angular路由的选项CSS的大小

  • dist/main-[es-version].[hash].js您的应用程序已捆绑[ES5大小:153 KB,新Angular CLI应用程序为空, 37 KB 已压缩]。
  • dist/polyfill-[es-version].[hash].bundle.js捆绑的polyfill依赖项(@angular,RxJS ...)[ES5大小:110 KB用于新的Angular CLI应用程序为空, 32 KB 压缩]。
  • dist/index.html您的申请的入口点。
  • dist/runtime-[es-version].[hash].bundle.js webpack loader
  • dist/style.[hash].bundle.css样式定义
  • 从Angular CLI资产配置中复制的
  • dist/assets资源

部署

您可以使用启动本地HTTP服务器的ng serve --prod命令预览应用程序,以便使用http://localhost:4200访问包含生产文件的应用程序。

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

答案 1 :(得分:54)

2.0.1 Final使用Gulp(TypeScript - 目标:ES5)

OneTime设置

  • npm install(当direcory为projectFolder时在cmd中运行)

捆绑步骤

  • npm run bundle(当direcory为projectFolder时在cmd中运行)

    捆绑包生成 projectFolder / bundles /

输出

  • bundles/dependencies.bundle.js [尺寸:~1 MB (尽可能小)]
    • 包含rxjs和角度依赖项,而不是整个框架
  • bundles/app.bundle.js [尺寸:取决于您的项目,我的 ~0.5 MB ]
    • 包含您的项目

文件结构

  • 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 (与Quickstart guide相同,只显示了捆绑所需的devDependencies和npm-scripts)

{
  "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"
  }
}
  • projectFolder / systemjs.config.js (与Quickstart guide相同,暂不提供)

(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 (生产) - 脚本代码的顺序至关重要。在bundle标记之后放置dist-systemjs.config.js标记仍然允许程序运行,但依赖包将被忽略,并且将从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 :(得分:22)

带Webpack的Angular 2(无CLI设置)

1- Angular2团队的教程

Angular2团队发布了使用Webpack的tutorial

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

<强>说明

  • npm install

  • npm start 。为了发展。这将创建一个虚拟的“dist”文件夹,该文件夹将在您的本地主机地址进行实时重载。

  • npm run build 。用于生产。 “这将创建一个物理”dist“文件夹版本,而不是可以发送到网络服务器.dist文件夹是7.8MB,但实际上只需要234KB即可在网络浏览器中加载页面。

2 - Webkit入门套件

这个Webpack Starter Kit提供了比上述教程更多的测试功能,并且看起来很受欢迎。

答案 3 :(得分:15)

使用SystemJs builder和gulp

的Angular 2生产工作流程

Angular.io有快速入门教程。我复制了这个教程并扩展了一些简单的gulp任务,用于将所有内容捆绑到dist文件夹,可以将其复制到服务器并像这样工作。我尝试优化一切以便在Jenkis CI上运行良好,因此可以缓存node_modules而不需要复制。

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

生产步骤
  1. 清理打包的js文件和dist文件夹
  2. 编译app文件夹中的打字稿文件
  3. 使用SystemJs bundler将所有内容捆绑到dist文件夹,并生成用于浏览器缓存刷新的哈希值
  4. 使用gulp-html-replace将index.html脚本替换为捆绑版本并复制到dist文件夹
  5. 将资产文件夹内的所有内容复制到dist文件夹
  6. 节点:虽然你总是可以创建自己的构建过程,但我强烈建议使用angular-cli,因为它具有所有需要的工作流程,现在它可以很好地工作。我们已经在生产中使用它,并且根本没有任何与angular-cli有关的问题。

答案 4 :(得分:14)

Angular CLI 1.x.x(适用于Angular 4.x.x,5.x.x)

这支持:

  • Angular 2.x和4.x
  • 最新的Webpack 2.x
  • Angular AoT编译器
  • 路由(正常和懒惰)
  • SCSS
  • 自定义文件捆绑(资产)
  • 其他开发工具(linter,unit&amp; end-to-end test settingss)

初始设置

ng new project-name --routing

您可以为SASS .scss支持添加--style=scss

您可以添加--ng4以使用Angular 4而不是Angular 2.

创建项目后,CLI将自动为您运行npm install。如果您想要使用Yarn,或者只是想在没有安装的情况下查看项目框架,check how to do it here

捆绑步骤

项目文件夹内:

ng build -prod

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

这也为更小的包执行AoT编译(没有Angular编译器,而是生成的编译器输出)。如果你使用Angular 4,因为生成的代码较小,所以使用AoT的包很小 您可以通过运行ng build --aot在开发模式(源图,无缩小)和AoT中使用AoT测试您的应用。

输出

默认输出目录为./dist,但可以在./angular-cli.json中进行更改。

可部署文件

构建步骤的结果如下:

(注意:<content-hash>指的是文件内容的哈希/指纹,这意味着缓存破坏方式,这是可能的,因为Webpack自己写了script标签)

  • ./dist/assets
    ./src/assets/**
  • 按原样复制的文件
  • ./dist/index.html
    ./src/index.html开始,在向其添加webpack脚本之后 源模板文件可在./angular-cli.json
  • 中配置
  • ./dist/inline.js
    小型webpack装载机/ polyfill
  • ./dist/main.<content-hash>.bundle.js
    主.js文件,包含生成/导入的所有.js脚本
  • ./dist/styles.<content-hash>.bundle.js
    当您使用CSS的CSSpack加载器(这是CLI方式)时,它们通过JS加载

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

其他档案

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

  • ./out-tsc/
    来自./src/tsconfig.json的{​​{1}}
  • outDir
    来自./out-tsc-e2e/的{​​{1}}
  • ./e2e/tsconfig.json
    来自AoT编译器(不可配置,不需要从beta 16开始使用CLI)

答案 5 :(得分:5)

截至今天,我仍然发现Ahead-of-Time Compilation cookbook是生产捆绑的最佳配方。您可以在此处找到它:https://angular.io/docs/ts/latest/cookbook/aot-compiler.html

到目前为止,我对Angular 2的体验是,AoT创建了最小的构建,几乎没有加载时间。最重要的是,这里的问题是 - 您只需要将一些文件发送到生产中。

这似乎是因为Angular编译器不会随生产版本一起提供,因为模板已经编译好了#34;提前时间&#34;。将HTML模板标记转换为javascript指令也非常酷,这些指令很难逆向工程到原始HTML中。

我制作了一个简单的视频,其中我演示了开发版与AoT版本中的Angular 2应用程序的下载大小,文件数量等 - 您可以在此处看到:

https://youtu.be/ZoZDCgQwnmQ

您可以在此处找到视频中使用的源代码:

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

答案 6 :(得分:2)

        **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.

答案 7 :(得分:2)

您可以使用github部署角度应用程序 angular-cli-ghpages

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

部署的网站将存储在github通常

的某个分支中

GH-页

使用可以克隆git分支并像服务器中的静态网站一样使用它

答案 8 :(得分:1)

“最佳”取决于场景。有时候你只关心最小的单个捆绑包,但在大型应用程序中你可能不得不考虑延迟加载。在某些时候,将整个应用程序作为一个捆绑包服务变得不切实际。

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

对于单个捆绑包,如果你感到勇敢,我会考虑Rollup或Closure编译器: - )

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

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

Angular版本:4.1.x

答案 9 :(得分:0)

只需在一分钟内使用webpack 3设置角度4,您的开发和生产ENV捆绑包就可以毫无问题地准备就绪 只需按照下面的github doc

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

答案 10 :(得分:0)

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

ng build --prod --aot --base-href。

答案 11 :(得分:0)

ng服务作品用于为开发目的服务我们的应用程序。生产呢?如果我们查看package.json文件,可以看到可以使用以下脚本:

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

构建脚本使用带有--prod标志的Angular CLI的ng构建。让我们现在尝试。我们可以通过以下两种方式之一进行操作:

#使用npm脚本

npm run build

#直接使用cli

ng build --prod

这次我们得到的是四个文件,而不是五个。 --prod标志告诉Angular使我们的应用程序更小。