詳解為生產(chǎn)環(huán)境編譯Angular2應(yīng)用的方法
Angular 2 已經(jīng)發(fā)布了 2.1.2 版本, 相信很多人已經(jīng)在使用(試用)了, 相比 AngularJS 1.x , Angular 2 在性能上有了長足的進(jìn)步, 同時(shí) Angular 2 也變得非常的龐大, 動(dòng)輒幾兆的腳本, 如何部署到生產(chǎn)環(huán)境? 接下來就介紹如何為生產(chǎn)環(huán)境編譯 Angular 2 應(yīng)用, 在本文中, 我們將 Angular 2 官方文檔中的 Hello Angular
應(yīng)用編譯到 50K 以下, 以用于生產(chǎn)環(huán)境。
未經(jīng)優(yōu)化的應(yīng)用
根據(jù) Angular2 官方的 QuickStart 快速創(chuàng)建一個(gè) Hello Angular
應(yīng)用, 在沒有任何優(yōu)化的情況下, 運(yùn)行情況如下圖所示:
從上圖可以看出, 僅僅一個(gè) Hello 應(yīng)用, 就產(chǎn)生了 40 個(gè)請求, 加載了 1.8M 的腳本, 這個(gè)在生產(chǎn)環(huán)境下(特別是移動(dòng)端)是無法接受的。
要看這一步的完整源代碼, 請移步 GitHub 。
打包與壓縮
傳統(tǒng)的方式無非就是進(jìn)行打包和壓縮, 我使用 browserify 和 uglifyjs 來進(jìn)行打包與壓縮, 首先是安裝這兩個(gè)工具類庫:
npm i -D browserify uglifyjs
在 package.json 文件中添加這兩個(gè) npm 命令:
{ "scripts": { "bundle": "browserify -s main app/main.js > dist/bundle.js", "minify": "uglifyjs dist/bundle.js --screw-ie8 --compress --mangle --output dist/bundle.min.js" } }
現(xiàn)在運(yùn)行這兩個(gè)命令, 看看會(huì)怎么樣:
npm run bundle && npm run minify
經(jīng)過一大堆 WARN 之后, 沒有出現(xiàn) ERROR , 也沒有出現(xiàn) npm-debug.log 文件, 證明沒有錯(cuò)誤, 現(xiàn)在來分析一下大?。?/p>
ls -hl dist -rw-r--r-- 1 zhang staff 1.4M Nov 14 14:08 bundle.js -rw-r--r-- 1 zhang staff 528K Nov 14 14:10 bundle.min.js
bundle.js 有 1.4M , 不過 bundle.min.js 被壓縮到了 528K , 看起來還不錯(cuò), 還可以再優(yōu)化一下, 那就是 gzip 壓縮, 通常在服務(wù)器上都會(huì)啟用:
gzip dist/bundle.min.js -c > dist/bundle.min.js.gz && ls -hl dist -rw-r--r-- 1 zhang staff 1.4M Nov 14 14:08 bundle.js -rw-r--r-- 1 zhang staff 528K Nov 14 14:10 bundle.min.js -rw-r--r-- 1 zhang staff 129K Nov 14 14:15 bundle.min.js.gz
經(jīng)過 gzip 之后, bundle.min.js.gz 有 129K , 似乎應(yīng)該可以了吧? 但是我覺得還有優(yōu)化的空間。
要看這一步的完整源代碼, 請移步 GitHub 。
AOT 以及 Tree Shaking
ES2016 (ES6) 有一個(gè)很重要的特性, 那就是 Tree Shaking , 可以移除項(xiàng)目中不需要的部分, 接下來我們使用 rollup 進(jìn)行 Tree Shaking 。
為了能夠使用 Tree Shaking , 我們需要將項(xiàng)目中的 TypeScript 編譯成 ES2015 腳本, 需要修改 TypeScript 配置, 新建一個(gè) tsconfig-es2015.json
的配置文件, 內(nèi)容如下:
{ "compilerOptions": { "target": "es2015", "module": "es2015", "moduleResolution": "node", "declaration": false, "removeComments": true, "noLib": false, "emitDecoratorMetadata": true, "experimentalDecorators": true, "lib": ["es6", "es2015", "dom"], "sourceMap": true, "pretty": true, "allowUnreachableCode": false, "allowUnusedLabels": false, "noImplicitAny": true, "noImplicitReturns": true, "noImplicitUseStrict": false, "noFallthroughCasesInSwitch": true, "typeRoots": [ "./node_modules/@types", "./node_modules" ], "types": [ ] }, "files": [ "app/main-aot.ts" ] }
在 Angular2 應(yīng)用中, 包含了一個(gè)即時(shí)編輯器 (JIT) , 在預(yù)編譯好的應(yīng)用中不是必需的, 使用 Angular2 的 AOT 編譯可以移除即時(shí)編譯器 (JIT) , 因此需要先安裝 Angular 的編譯器:
npm i -D @angular/compiler-cli
為了使用 aot 編譯出來的文件, main.ts 文件也要做相應(yīng)的修改, 將 main.ts 文件另存為 main-aot.ts , 修改內(nèi)容如下:
import { enableProdMode } from '@angular/core'; import { platformBrowser } from '@angular/platform-browser'; import { AppModuleNgFactory } from './app.module.ngfactory'; enableProdMode(); const platform = platformBrowser(); platform.bootstrapModuleFactory(AppModuleNgFactory);
不再使用 platform-browser-dynamic
, 改為使用 platform-browser
。
同時(shí) index.html 也另存為 index-aot.html
, 也做相應(yīng)的修改, 不在加載 system.js , 改為直接使用最終的 aot 腳本:
<!-- <script src="node_modules/systemjs/dist/system.src.js"></script> --> <!-- 2. Configure SystemJS --> <!-- <script src="systemjs.config.js"></script> <script> System.import('app').catch(function(err){ console.error(err); }); </script> --> </head> <!-- 3. Display the application --> <body> <my-app>Loading...</my-app> <script src="dist/bundle-aot.min.js"></script> </body>
接下來的整體的思路是:
1、使用 ngc 進(jìn)行 aot 編譯;
npm run ngc -- -p tsconfig-es2015.json
這一步將會(huì)生成一系列 *.ngfactory.ts *.module.metadata.json
臨時(shí)文件, 可以更新 .gitignore
來忽略這些文件, 避免對代碼庫造成污染;
2、將 typescript 文件編譯成 es2015 (es6) 腳本;
npm run tsc -- -p tsconfig-es2015.json
3、使用 rollup 進(jìn)行 tree shaking , 移除項(xiàng)目不使用的功能;
rollup -f iife -c rollup.config.js -o dist/bundle-aot-es2015.js
4、再次使用 typescript 將 tree shaking 之后的腳本編譯成 es5 腳本;
tsc --target es5 --allowJs dist/bundle-aot-es2015.js -out dist/bundle-aot.js
5、使用 uglifyjs 再次壓縮上一部生成的 es5 腳本;
uglifyjs dist/bundle-aot.js --screw-ie8 --compress --mangle --output dist/bundle-aot.min.js
這幾個(gè)命令對應(yīng)的 npm 腳本如下:
{ "scripts": { "ngc": "ngc", "rollup": "rollup -f iife -c rollup.config.js -o dist/bundle-aot-es2015.js", "es5": "tsc --target es5 --allowJs dist/bundle-aot-es2015.js -out dist/bundle-aot.js", "minify-aot": "uglifyjs dist/bundle-aot.js --screw-ie8 --compress --mangle --output dist/bundle-aot.min.js", "prod-aot": "npm run ngc -- -p tsconfig-es2015.json && npm run tsc -- -p tsconfig-es2015.json && rollup && npm run es5 && npm run minify-aot" } }
最終只要運(yùn)行一個(gè)命令即可:
npm run prod-aot
最后來看一下最終的文件大?。?/p>
ls -hl -rw-r--r-- 1 zhang staff 595K Nov 14 15:59 bundle-aot-es2015.js -rw-r--r-- 1 zhang staff 669K Nov 14 16:01 bundle-aot.js -rw-r--r-- 1 zhang staff 194K Nov 14 16:01 bundle-aot.min.js -rw-r--r-- 1 zhang staff 46K Nov 14 16:02 bundle-aot.min.js.gz -rw-r--r-- 1 zhang staff 1.4M Nov 14 15:54 bundle.js -rw-r--r-- 1 zhang staff 528K Nov 14 15:54 bundle.min.js -rw-r--r-- 1 zhang staff 129K Nov 14 16:02 bundle.min.js.gz
最終生成的 bundle-aot.min.js.gz 只有 46K , 比沒有使用 aot 編譯的最終文件 bundle.min.js.gz 少了將近 2/3 , 可以說 aot + tree shaking 效果非常的顯著。
要看這一步的完整源代碼, 請移步 GitHub 。
經(jīng)過這樣的終極編譯優(yōu)化編譯之后, 應(yīng)該可以放心的部署到生產(chǎn)環(huán)境了。
參考資料:
Angular Quick Start
AoT Compilation
Building an Angular 2 Application for Production
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
ANGULARJS中用NG-BIND指令實(shí)現(xiàn)單向綁定的例子
這篇文章主要介紹了ANGULARJS中用NG-BIND指令實(shí)現(xiàn)單向綁定的例子,本文簡單介紹AngularJS框架后,用一個(gè)實(shí)例演示{{}}插值法和ng-bind指令的使用,需要的朋友可以參考下2014-12-12AngularJS中的API(接口)簡單實(shí)現(xiàn)
本文主要介紹AngularJS API(接口),這里對AngularJS API的知識(shí)做了詳細(xì)講解,并附簡單代碼實(shí)例,有需要的小伙伴可以參考下2016-07-07AngularJS頁面帶參跳轉(zhuǎn)及參數(shù)解析操作示例
這篇文章主要介紹了AngularJS頁面帶參跳轉(zhuǎn)及參數(shù)解析操作,結(jié)合具體實(shí)例形式分析了AngularJS使用URL傳遞參數(shù)及參數(shù)的接收、解析等相關(guān)操作技巧,需要的朋友可以參考下2017-06-06掌握Queries設(shè)計(jì)模式優(yōu)化Angular應(yīng)用開發(fā)技巧
這篇文章主要介紹了掌握Queries設(shè)計(jì)模式優(yōu)化Angular應(yīng)用開發(fā)的技巧示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10Angular.JS讀取數(shù)據(jù)庫數(shù)據(jù)調(diào)用完整實(shí)例
這篇文章主要介紹了Angular.JS讀取數(shù)據(jù)庫數(shù)據(jù)調(diào)用,結(jié)合完整實(shí)例形式分析了AngularJS使用$http.get方法與后臺(tái)php交互讀取數(shù)據(jù)庫數(shù)據(jù)相關(guān)操作技巧,需要的朋友可以參考下2019-07-07詳解Angularjs 自定義指令中的數(shù)據(jù)綁定
這篇文章主要介紹了Angularjs 自定義指令中的數(shù)據(jù)綁定,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-07-07