iT邦幫忙

DAY 20
1

我在前端 ng 時系列 第 20

開發 AngularJS 的工具 - gulp

簡單介紹一下目前開發 AngularJS 的工具 - gulp。

gulp 是幫助前端開發的工具,幫助我們 complie 語法或優化效能 (minify 或 concat js 等)。
網路上有很多大大都有介紹 gulp 跟實際用法,要不然看官網學也很快。
心動不如馬上行動 -> 官網

今天只會帶到一點在開發 AngularJS 會使用到的 gulp 套件,
假如你/或你身邊有再寫 AngularJS 可是沒有用任何工具去優化效能的人。請務必試試~


我們目前使用 gulp 是主要完成 minify 跟 concat 的部分。

minify:
minify AngularJS 會有兩步驟。

  1. 依照 AngularJS DI 的特性,做壓縮的檢查。
  2. 壓縮 uglify

1. ng-annotate

先岔題來說一下 AngularJS 使用 DI 的其中兩種方式。

  • Implicite Dependencies
    function 裡 argument 的名稱就是要 DI 的 service 名稱,所以不能變更

    app.controller(‘MyCtrl’, function ($scope, service) {
    /..../
    })

  • Inline Array Annotation
    把 DI 名稱改寫成 array 形式,在 function 的名稱就可以變更

    app.controller(‘MyCtrl’, [‘$scope’, ‘myService’, function ($scope, s) {
    /..../
    })

回到壓縮 AngularJS 話題。
假如使用 Implicite Dependencies 的方式下壓縮。
在壓縮的過程中,壓縮會把 argument 名稱也壓縮到,導致 AngularJS 的 DI 無法找到指定的 service 而壞掉。

ex: (壓縮後)

angular.module("a").controller("b", function (c,d) {...});
// Error: [$injector:unpr] Unknown provider: cProvider <- c
AngularJS  不知道 c 跟 d 分別代表什麼 dependency

ng-annotate 就是幫我們把程式裡有用到 DI 的地方都幫我們轉換成 Inline Array Annotation。
確保程式在壓縮的時候就不會壞掉了!

ex: (壓縮後)

// work well!!
angular.module("a").controller("b", ['$scope', '$timeout', function (c,d) {...}]);

所以說壓縮檔案前, 一定要先讓 ng-annotate 檢查一下.
(我的習慣是要求自己先寫好 inline array annotation, 之後使用 ng-annotate 求心安~)

目前的 gulp task
gulp.src(’src')
.pipe(ngAnnotate())
.pipe(gulp.dest, ‘/dist/'));

壓縮 uglify:
加壓縮是先載入 uglify 工具後,確認跑完 ng-annotate 之後再執行。
gulp.src(’src')
.pipe(ngAnnotate())
.pipe(uglify())
.pipe(gulp.dest, ‘/dist/'));

concat:
concat 主要目的就是把你的檔案都連結在一起,讓客戶端只要只載入一份 JavaScript 檔案就好。
大大的提升因為載入太多隻檔案發生的塞車。
(尤其是 AngularJS module 觀念,使得程式的 JavaScript 的分散在多隻 JavaScript 檔案)

讓壓縮後的檔案都連接在一起。
// ‘all.min.js’ 是 concat 後 output 出來的檔名
gulp.src(’src')
.pipe(ngAnnotate())
.pipe(uglify())
.pipe(concat, 'all.min.js')
.pipe(gulp.dest, ‘/dist/'));


順利的跑完上面的 gulp task 後,會發現 minify 後的檔案其實非常不好 debug...
尤其還在測試階段的話,就不要自己害自己了。
把 gulp task 寫成兩種 task。

附上完整的程式:

var  gulp = require('gulp’),
       concat = require('gulp-concat'),
       ngAnnotate = require('gulp-ng-annotate'),
       uglify = require('gulp-uglify’);

// 上面沒有細講。
// 在檔案更新的時候,幫我們跑 task 。不用每次都手動跑 task
gulp.task('watch', function() {
    // 開始 watch 就先幫我們建一份出來
    gulp.start('developer');
    gulp.watch('/app/**/*.js', ['developer']);
});

gulp.task(’developer’), function () {
    // 在 debug 階段,只要跑 concat 就好
    gulp.src(’src')
        .pipe(concat, 'all.min.js')
        .pipe(gulp.dest, ‘/dist/'));
}

// build 階段在跑 minify + concat
gulp.task(’build’), function () {
    gulp.src(’src')
        .pipe(ngAnnotate())
        .pipe(uglify())
        .pipe(concat, 'all.min.js')
        .pipe(gulp.dest, ‘/dist/'));
}

ng-Annotation, uglify, concat 在 grunt 也有,假如習慣用 grunt 的朋友也可以選擇 grunt ~

除了 ng-Annotation, uglify, concat,gulp 跟 grunt 還有很多工具方便我們使用。
ex:
rimraf 在跑前清除前一份 build 好的檔案,避免奇怪事發生。
ngHtml2js 幫我們把 template 都先放在 $templateCache module,
我們只要下載一份 $templateCache JavaScript 檔案就好。
還有 gutil, lazypipe, htmlmin 等等很多工具可以去尋找!!


番外篇:Bower
Bower 是管理開發 application 需要的 package。
我們主要是拿來下載 bootstrap 跟 angular 的套件 (ui-router, angular-sanitize, etc)
等把 package 下載好後,在用現在的 gulp-concat 把需要的 library concat 成一份 JavaScript 檔案。
有鑑於網路上有很多教學... 我就不寫方法了。(飄走)
bower 官網


上一篇
初談 directive - 番外篇 - 傳送函式進 directive
下一篇
SEO for AngularJS Website
系列文
我在前端 ng 時30

尚未有邦友留言

立即登入留言