2016年11月29日火曜日

[WEB] gulp with angular

gulp是一個基於node.js的資料流概念的處理器。對gulp的介紹請參考其他文章的解說。
http://www.oxxostudio.tw/articles/201503/gulp-install-webserver.html

當然一般是拿來做web的html/css/js的後處理。例如置換/minify/uglify...
本文只討論一些非正常安裝的project會遇到的狀況跟解法。

事前準備:

  • 安裝node.js。
  • 初始化一個新的project。或是從其他地方取得要開發的project的相關檔案。在此定義路徑為<project root>。必須有node_modules這個目錄跟package.json這檔案。
  • 在<project root>下面安裝gulp跟相關package。本文裡面用的幾個package:
gulp:主執行元件。
del :刪除檔案。在執行處理前建議把之前做出來的檔案刪除。
gulp-html-replace:替換html內的script定義的元件。在此例是用來替換開發時的分散script檔案,經過結合之後成為單一檔案的檔名。

例,gulp內的指令:
htmlreplace({'js': 'js/all.min.js', 'css': 'css/all.min.css'})

原本html內的代碼:
  <!-- build:js -->
  <script src="js/a.js"></script>
  <script src="js/b.js"></script>
  <script src="js/c.js"></script>
  <!-- endbuild -->
  <!-- build:css -->
  <script src="css/a.css"></script>
  <script src="css/b.css"></script>
  <script src="css/c.css"></script>
  <!-- endbuild -->
會被替換成
  <script src="'js/all.min.js"></script>
  <script src="'css/all.min.css"></script>

被包在<!-- build:xxx --><!-- endbuild --> 裡面的script src tag會被替換成對應的文字。

gulp-minify-html:html minify用的元件。會把html裡面的換行/註解等等東西移除。
gulp-minify-css:css minify用的元件。會把css裡面的換行/註解等等東西移除。
gulp-uglify:js minify用的元件。會把js裡面的換行/註解等等東西移除以外。還會把js的變數名稱替換為無意義的短文字。
gulp-concat:連接檔案。若是gulp task指定的src檔案有很多個的話,使用此元件處理過的話,輸出將會只有一個檔案。
gulp-rename:更名。在這裡用來把輸入的檔案在輸出的時候全部冠上".min"的後綴名稱。這是web開發在經過minified之後的檔名的命名習慣。
gulp-ng-annotate:針對angular的定義的後處理。因為uglify會把函式的參數修改命名,會使angular的參數注入失效。也就是直接uglify輸出之後的angular程式碼可能會無法動作。經由此元件處理之後,會改寫成以字串注入,因此可以維持住原本的參數名稱。


  • 開始撰寫gulp用的script: gulpfile.js。此檔名不可以更改。在此以一個範例檔案解說。


//首先,把所有剛剛安裝的元件全部取進來用。
var gulp      = require('gulp'),
  concat      = require('gulp-concat'),
  minifyCSS   = require('gulp-minify-css'),
  uglify      = require('gulp-uglify'),
  rename      = require("gulp-rename"),
  htmlreplace = require('gulp-html-replace'),
  del = require('del'),
  minifyHTML  = require('gulp-minify-html'),
  ngAnnotate = require('gulp-ng-annotate');


gulp.task('concat', function() {   //此task是為了把所有的css連成一個檔案。第一個參數是task name。之後的gulp.start()裡面需用此task name描述需做的動作。
  return gulp.src([
   "./css/a.css"
  ,"./css/b.css"
  , "./css2/*"
  ])  //來源有多檔案的話可以陣列表示。也可以用wildcard。
    .pipe(concat('all.css'))  //指定處理動作。參數為處理完之後的輸出檔名。
    .pipe(gulp.dest('./build/css/'));  //指定輸出路徑。

  // 因為javascript 資料流的設計是非同步,可以並行的。使用return的寫法是為了保證此動作做完之後才會進行下一個動作。
};

gulp.task('minifyCSS', ['concat'], function() {  //示範task之間的相依寫法。若是該task在執行之前必須做其他的事情,使用第二參數指定其相依的task。
  return   return gulp.src('./build/css/all.css')  //來源只有一個檔案的話直接指定檔名。在此我們指定concat task執行完成之後產生的檔案「./build/css/all.css」。
    .pipe(minifyCSS({
      keepBreaks: true,
    }))  // 執行CSS壓縮。
    .pipe(rename(function(path) {
      path.basename += ".min";
      path.extname = ".css";
    }))  // 更名。
    .pipe(gulp.dest('./build/css/'));  //指定輸出路徑。
});



gulp.task('minifyHTML', function() {  //壓縮html。並改動含入的script tag。
  var opts = {comments:false, spare:false, quotes:true};  //參數也可以使用變數指定。
  return gulp.src([
   './*.html'
  ])
    .pipe(htmlreplace({
        'js': 'js/all.min.js',
        'css': 'css/all.min.css'
    }))  //把產出的壓縮過的css跟js檔名帶入。
    .pipe(minifyHTML(opts))
    .pipe(gulp.dest('./build/'));
});

gulp.task('uglifyJS', function() {
  return gulp.src([
  './js/*.js'
  ])
    .pipe(concat('all.js'))  //把js檔案組合成一個大檔。
    .pipe(ngAnnotate())  //維持angular的參數注入名稱。
    .pipe(uglify())  //修改參數名,讓js碼難讀。也會拿掉註解跟換行碼。
    .pipe(rename(function(path) {
      path.basename += ".min";
      path.extname = ".js";
    }))
    .pipe(gulp.dest('./build/js/'));
});

gulp.task('clean', function() {  //在執行流程之前,建議把輸出處理過的檔案的專用目錄裡面的檔案全部刪除。產出處理過的檔案的目錄,最好是一個乾淨的空目錄。不要跟開發檔案混在一起。本例的「build」就是一個乾淨的空目錄。
    return del(['./build/']);
});

gulp.task('default', ['clean'], function() {  //執行gulp.
  gulp.start('minifyHTML','minifyCSS', 'uglifyJS');  //這裡指定的task會同時執行。
});



辛苦的寫完處理程序之後... 怎麼執行?
不是正常安裝的project,可能會遇到路徑問題。gulp在安裝之後,應該會出現在<project root>/node_modules/.bin/gulp,
所以在<project root>下面執行 ./node_modules/.bin/gulp 即可。




0 件のコメント:

コメントを投稿