介紹Gulp套件與展示一個網頁最佳化的demo,並且透過concat的套件解決兩個獨立的js檔案但有循環參考的解法
Gulp的介紹與使用情境
一般我們在做前端開發的時候都會遇到需要做一系列的”工作“達到前端資源最佳化的處理,避免有多於的請求去拿過多過大或是為最佳化處理的檔案.Gulp就是一個為了解決這樣問題而產生的npm 套件.
Gulp本身實做了一個很簡單的機制去把我們指定資源(source resource)透過串流(streaming)的方式處理到指定位置(output destination).
Gulp包含以下特色:
- Automation - 可以幫你建置可重複執行的指令去達成繁瑣的開發/發佈流程(development workflow).
- Platform-agnostic - 主要的IDE 包含不同的平台: PHP, .NET, Node.js, Java 都有支援的套件.
- Strong Ecosystem - 以js開發並可以直接引用js的package增加你的應用.
- Simple - 提供介面街口讓你可以簡單的呼叫gulp參數.
Setup
- Install Nodejs
exec cmd to install Gulp CLI
npm install gulp -g
Basic Gulp using
一個簡單的gulpfile.js架構如下:
1 | var gulp = require('gulp'); |
這邊如果我們在cmd執行gulp指令就可以清除public資料夾內的所有資料,而這邊我們是使用del這個gulp套件來幫我們處理中間的過程.
Make Task Execute by Sequence
接下來,如果我們今天的情境是要有兩個task,如:
- 先清空資料
- 將指定檔案移入該資料夾
1 | var gulp = require('gulp'); |
這邊我們可以看到我們在原本的指令重新命名為clean後,將它放入default這個工作的第二個參數內,這邊第二個參數裡面的放入的task名稱會在default執行前,先並行裡面的工作,做完才執行default內的工作.
可想像到的如果第二個參數內有多個工作,在Gulp原先的設計依照javascipt語言的特性我們無法控制它的先後順序,這在實務上會很不方便.而這邊特別介紹run-sequence這套件可以建立js有相依性的系列工作,協助我們解決在有必要依序執行的工作上做更彈性的設置.當我們引入後上面程式碼就可以做下面修改:
1 | var gulp = require('gulp'); |
針對run-sequence的更多細節可以參考先前另外一篇的Gulp run-sequence - Run a Series of Dependent Gulp Tasks in Order
JS Bundle with Gulp
而實務上我們會遇到要幫前端做最佳化的案例,這邊我們就可以用gulp-concat,gulp-uglify與gulp-clean-css來依序幫我們達到js,css檔案合併與js,css的壓縮最佳化.
1 | var gulp = require('gulp'); |
這邊我們刻意在執行minify-css的task時將執行時間印出來.而runSequence這邊我們可以分成下面幾個動作:
- 清空資料夾
- 搬移js, css檔案
- 合併產生app.js, app.css檔案
- 最佳化產生app.min.js, app.min.css檔案
Demo : Solving JS File Cycling Refence Problem
而今天實務上有一個範例,情境如下:
某一html有引入兩個js檔案,但兩個檔案內彼此在執行上會互相呼叫對方寫好的function(cycling reference),參考如下:
index.html:
1 |
|
lib-a.js:
1 | function printMsg(msg){ |
lib-b.js:
1 | function testFunctionInB(msg){ |
這邊我們可以很清楚的看到當兩個檔案依序從body被載入時,如果lib-b.js在lib-a.js之後才被載入會有以下錯誤:
今天如果我們使用傳統的資源載入方式無法解決這種functionA=>functionB=>functionA的問題,因為這就跟雞生蛋還是蛋生雞的問題一樣無解.
但如果我們使用上幾步驟介紹到的bundle作法,則可以幫我們把檔案合併至單一檔案內,自然這樣的問題就可以被處理了.
如果對上面這個案例有興趣的朋友可以參考原始碼
通常這種問題是比較早開發的js才會有的,現在的js開發強調模組化與封裝,所以我們應該多利用這樣的特性避開這個問題.