iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 25
0
Modern Web

Angular 2 之 30 天邁向神乎其技之路系列 第 25

[Day 25] Angular 2 事先編譯 Ahead-of-Time (AoT)

前言

Angular 2 雖然是一套強大框架,但最後輸出仍然為 htmljscss 檔案,js 本身是即時編譯 (Just-in-Time, JiT),瀏覽器先讀取我們的檔案,然後瀏覽器邊看邊編譯,但這樣比起有先編譯過當然慢了多,如果事先編譯 (Ahead-of-Time, AoT) 的話,當我們用瀏覽器打開時,就不用編譯,於是體驗速度就快了許多,此外編譯過的程式碼也會比原始碼輕量。由於先編譯過,如果有 bug 的話也會很容易發現。

AoT

在 Angular 2 中有幾種方式可以建構 AoT 網頁:
1.使用開發環境
2.直接使用 ngc
3.@ngtools/webpack 套件

如果要建立 AoT 要做多設定,後面兩種屬於要自己重頭硬幹的方式,介紹起來真的很複雜,所以我簡單帶過,通常我們也不需要這樣做。附上一些文章供大家參考:
官方文件
Ahead-of-Time Compilation in Angular
Building an Angular 2 Application for Production

1.使用開發環境

這邊開發環境是指 Angular-Seed 這類的環境,或是別人已經打包好的 AoT 開發專案直接拿來使用。

Angular-Seed

Angular-Seed 是 Angular 第二受歡迎的開發環境

$ git clone --depth 1 https://github.com/mgechev/angular-seed.git
$ cd angular-seed

# 安裝套件
$ npm install
# 快一點安裝套件 (用 Yarn: https://yarnpkg.com)
$ yarn install  # or yarn

# AoT compilation 編譯檔案,檔案會產生在 `dist/prod`
$ npm run build.prod.aot

2.ngc

採用 Angular CLI 開發

首先要安裝套件

npm install @angular/compiler-cli @angular/platform-server --save

建立一個 tsconfig-aot.json

{
  "compilerOptions": {
    "target": "es5",
    "module": "es2015",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "lib": ["es2015", "dom"],
    "noImplicitAny": true,
    "suppressImplicitAnyIndexErrors": true
  },

  "files": [
    "app/app.module.ts",
    "app/main.ts"
  ],

  "angularCompilerOptions": {
   "genDir": "aot",
   "skipMetadataEmit" : true
 }
}

編譯

node_modules/.bin/ngc -p tsconfig-aot.json

Bootstrap 也要調整

//app/main.ts

import { platformBrowser }    from '@angular/platform-browser';
import { AppModuleNgFactory } from '../aot/app/app.module.ngfactory';
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);

Rollup: 一種 treeshaking 的技巧,就是把多餘無用的 code 像搖樹般搖掉。
首先要安裝

npm install rollup rollup-plugin-node-resolve rollup-plugin-commonjs rollup-plugin-uglify --save-dev

然後增加一個 rollup-config.js 檔案

import rollup      from 'rollup'
import nodeResolve from 'rollup-plugin-node-resolve'
import commonjs    from 'rollup-plugin-commonjs';
import uglify      from 'rollup-plugin-uglify'

export default {
  entry: 'app/main.js',
  dest: 'dist/build.js', // output a single application bundle
  sourceMap: false,
  format: 'iife',
  plugins: [
      nodeResolve({jsnext: true, module: true}),
      commonjs({
        include: 'node_modules/rxjs/**',
      }),
      uglify()
  ]
}

執行 rollup

node_modules/.bin/rollup -c rollup-config.js

index.html 中用 SystemJS 的部分移除,改成:

<body>
  <my-app>Loading...</my-app>
</body>

<script src="dist/build.js"></script>

這樣就完成囉!

3.@ngtools/webpack

首先要裝這個套件

npm install -D @ngtools/webpack

設定成 development dependency

接著加入 Webpack configuration 檔案 webpack.config.js,並加入以下內容:

import {AotPlugin} from '@ngtools/webpack'

exports = { /* ... */
  module: {
    rules: [
      {
        test: /\.ts$/,
        loader: '@ngtools/webpack',
      }
    ]
  },

  plugins: [
    new AotPlugin({
      tsConfigPath: 'path/to/tsconfig.json',
      entryModule: 'path/to/app.module#AppModule'
    })
  ]
}

這邊 @ngtools/webpack 會取代 typescript 載入器像是 ts-loaderawesome-typescript-loader。 這個套件會和 AotPlugin 一起完成 AoT 編譯。


上一篇
[Day 24] Angular 2 + Ionic = Mobile App ( 4 ) 發布 App
下一篇
[Day 26] Angular 2 裝飾器 @ContentChild
系列文
Angular 2 之 30 天邁向神乎其技之路31

尚未有邦友留言

立即登入留言