最近在研究gulp,npm裡的文件有些過於簡潔,並看不出來到底每一步操作是為什麼,api到底是做什麼用。
於是各種查資料,看到一篇英文版的,說的不錯,趁著週末翻譯過來,以備我自己以後想看不用再翻譯一遍,也可以造福下正好看到這篇文章的同學。
Gulp現在是越來越流行了。它可以做的事情實在是太多了,比如,拼接js檔案,壓縮圖片。如果你是一個gulp.js的新手,建議從這篇文章開始入門吧!
在這個教程裡,你會了解怎麼使用gulp.js來實現一個應用了內建的livereload功能的本地web服務。
以前的實現方式
假設我們要開發一個單頁應用。這個app的入口是index.html。我們的目標是可以讓瀏覽器通過localhost來訪問這個頁面。以前,你需要安裝一個Apache或者Nginx這樣的伺服器軟體來實現這樣的功能。
更棒的實現方式
時至今日,javascript無所不能了,就要稱霸天下了,甚至它都可以去實現一個web服務。這篇文章裡,我們就要用一個gulp的外掛,人稱gulp-connect。用這個外掛來實現一個WEB服務。
接下來的篇幅,我們就要來為我們的單頁應用來配置一個本地服務。
開始下文之前,我假定你已經把準備工作都已經做好了,比如gulpfile檔案已建好!
第一步,安裝
第一步,我們要來安裝下gulp-connect外掛。安裝的命令如下:
1 |
npm install --save-dev gulp-connect |
小提示:npm install –save-dev 可以簡寫為npm i -D
現在,我們來定義web服務,gulpfile.js的程式碼如下
1 2 3 4 5 6 7 8 |
var gulp = require('gulp'), connect = require('gulp-connect'); gulp.task('webserver',function(){ connect.server(); }) gulp.task('default',['webserver']); |
只要在終端執行gulp命令,然後在瀏覽器位址列輸入localhost:8080就可以看到index.html啦。
localhost:8080所指向的就是gulpfile檔案所在的那一級目錄。
在終端輸入ctrl+c會結束當前任務。
在github可以找到本文所有例子的原始碼。
點這裡看github
加入livereload的支援
建立一個基礎的web服務很簡單,是不是?那現在我們繼續來把livereload加入web服務中。
我們需要做兩件事情:
首先,告訴web服務啟動的時候執行livereload。
其次,在頁面有更新的時候通知livereload重新整理頁面。
第一步很簡單是不是,我們只要將livereload的屬性設定為true,將webserver這個任務寫成下面的樣子。
1 2 3 4 5 |
gulp.task('webtask',function(){ connect.server({ livereload:true }); }); |
第二步的話就取決於你具體的例項了。比如說,我們要將less檔案自動編譯成css樣式表,並讓其被瀏覽器識別。
我們來將這個例子分步處理下:
首先,需要一個’watcher’,用來監控less檔案的變化,監控到變化後這個’watcher’就會去觸發less的編譯器,將其輸出為一個css檔案。之後這個css檔案有更新了之後就會去通知livereload,讓其重新整理頁面。
在這個例子裡面,還需要用到gulp-less外掛。
外掛的安裝命令如下
1 |
npm install --save-dev gulp-less |
gulp裡已經有了watch這個方法,可以來充當’watcher’
我們的文件結構大致可以如下:
1 2 3 4 5 6 7 8 |
. ├── node_modules │ └── ... ├── styles │ └── main.less ├── gulpfile.js ├── index.html └── package.json |
watch任務執行的時候,gulp.js監聽styles資料夾裡less檔案的所有改動,當有改動的時候就會觸發less任務。每一次編譯之後,結果會自動返回給瀏覽器。
gulpfile.js檔案的程式碼如下所示(作者允許將下列程式碼使用於你自己的專案):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
var gulp = require('gulp'), connect = require('gulp-connect'), less = require('gulp-less'); gulp.task('webserver',function(){ connect.server({ livereload:true }); }); gulp.task('less',function(){ gulp.src('styles/main.less') .pipe(less()) .pipe(gulp.dest(styles)) .pipe(connect.reload()); }); gulp.task('watch',function(){ gulp.watch('style/*.less',['less']); }) gulp.task('default',['less','webserver','watch']); |
現在我們重新在終端執行gulp,然後再在瀏覽器開啟localhost:8080。做完這些,我們就可以試著在style資料夾的less檔案裡做一些改動。它會立即編譯並重新整理瀏覽器。看吧,這樣我們並不需要依賴什麼瀏覽器外掛,就可以實現頁面的自動重新整理啦!
一些小小調整
注意,我們之前寫的gulpfile.js檔案只是一個小小的示例用於示範怎麼來實現一個運用了livereload的web服務。我非常建議大家可以把將其他gulp外掛一起玩起來。
你也可以試著重新修改下你寫的各個task的結構,用一用不是gulp內建的watch方法,這個方法可以只監控有改動的檔案。這個對於以後你如果使用更大的程式碼庫來說尤為重要。
本教程的接下來部分,我們來看一看對於以上實現web服務的另一個方案。
更換Hostname和Port
gulp-connect外掛本身有很多可選的配置。比如說,你可以更改web服務的埠號或者hostname。你甚至可以用一個你習慣使用的hostname配上80埠(預設的是localhost:8080)
程式碼如下:
1 2 3 4 |
connect.server({ port:80, host:'gulp.dev' }); |
進行了這個配置之後,我們要在hosts檔案裡面加上gulp.dev,然後執行sudo gulp,因為要使用80埠的話,是需要管理員許可權的。
一些進階特性
你可以同時啟動多個web server。這個很有用的。比如說,如果你要同時啟動一個開發和一個測試的服務。
gulp-connect也可以設定多個根目錄。
比如,你要用coffeescript,然後將壓縮過得js檔案放到一個臨時的資料夾,那就可以在根目錄root中加上這個臨時的資料夾而不去影響原來的原始檔夾。
在GitHub上你可以獲得更多的示例,連結如下:
https://github.com/AveVlad/gulp-connect
重構我們的程式碼
在以上的例子中,我們只是寫了一個小小的將less編譯成css檔案,並讓其立即體現在瀏覽器中的例子。雖然它奏效了,但是我們可以做的更好。當把編譯和livereload混合起來用的時候,可能會有一些問題。所以,我們將他們拆分開來並用watch來監控。為此,就需要用到上面提到的gulp-watch外掛。
我們可以再加入一個coffeeScript的編譯步驟。這個增加的步驟會使我們的新結構更加清晰。
安裝新外掛的命令
1 |
npm install --save-dev gulp-watch gulp-coffee |
在gulpfile.js檔案的最頂部引用這兩個外掛。在下面的步驟中,我假設你已經在scripts資料夾裡有了以.coffee為字尾的檔案。
重寫的gulpfile檔案,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
var gulp = require('gulp'), connect = require('gulp-connect'), watch = require('gulp-watch'), coffee = require('gulp-coffee'), less = require('gulp-less'); gulp.task('webserver',function(){ connect.server({ live reload:true, root:['.','.tmp'] }); }); gulp.task('livereload',function(){ gulp.src(['.tmp/styles/*.css','.tmp/scripts/*.js']) .pipe(watch()) //注意此處的watch是gulp-watch外掛 .pipe(connect.reload()); }); gulp.task('coffee',function(){ gulp.src('scripts/*.coffee') .pipe(coffee()) .pipe(dest('.tmp/scripts')); }); gulp.task('less',function(){ gulp.src('styles/main.less') .pipe(less()) .pipe(gulp.dest('.tmp/styles')); }); gulp.task('watch',function(){ gulp.watch('style/*.less',['less']); gulp.watch('scripts/*.coffee',['coffee']); }) gulp.task('default',['less','coffee','watch','webserver','livereload']); |
最大的變化,是增加的livereload任務。這個任務僅僅是監聽了編譯之後的檔案,然後如果有變化就重新整理瀏覽器。watch()方法可以僅僅只重新載入有變化的檔案。gulp自帶的gulp.watch()會將整個專案都重新載入。
因為新增了livereload這個任務,我們就不需要在每一步的編譯之後都加上.pipe(connect.reload())了。所以,我們把每個任務按照他們各自關注的點分開定義,這樣對於專案開發來說比較好。
同時,我們也發現,編譯之後的檔案不再儲存至他們各自的資料夾去了。現在它們儲存在一個臨時資料夾.tmp中。資料夾的內容就是生成的檔案,它們儲存在臨時資料夾,不再去汙染scripts和styles資料夾。我們也建議不要將臨時資料夾加入版本控制系統。
我們要做的就是把臨時資料夾也視為一個根目錄。程式碼如下
1 |
root:['.','.tmp'] |
這邊經過我的測試,經過編譯之後會自動生成.tmp資料夾,這個資料夾裡有一個styles資料夾儲存css檔案有一個scripts資料夾儲存js檔案。然後我們的版本控制系統是git,那麼在.gitignore檔案裡就要寫上.tmp,不要讓.tmp這個臨時資料夾加入版本控制系統。因為在本地預覽,這樣html就得要能獲取到css和js檔案,那麼就在root裡把.tmp也設定為根目錄。這樣gulp執行的時候,就能讀取到css和js檔案啦~
提交git的話,就提交html,styles folder,scripts folder.
協同開發者如果clone的話,再執行下gulp就會再次生成臨時資料夾,進行預覽。
總結
現在,你已經可以用gulp來構建一個本地web服務了。你也可以嘗試和其他gulp外掛配合使用,來構建或者測試一個單頁應用。這裡的web服務僅僅是本地服務,如果你要作為生產,就得要用一些類似Nginx或者CDN這樣的高效解決方案。
Grunt及類似的專案都可以實現以上的功能,gulp只是提供了一個比較簡便的方法來實現這個功能。
譯文帶著我自己的實踐與想法,如果有翻譯的不對或者不好的地方,希望大家多多指教~
打賞支援我翻譯更多好文章,謝謝!
打賞譯者
打賞支援我翻譯更多好文章,謝謝!