gulp的使用以及Gulp新手入門教程
Gulp新手入門教程
Gulp 是一個自動化工具,前端開發者可以使用它來處理常見任務:
- 搭建web伺服器
- 檔案儲存時自動過載瀏覽器
- 使用前處理器如Sass、LESS
- 優化資源,比如壓縮CSS、JavaScript、壓縮圖片
當然Gulp能做的遠不止這些。如果你夠瘋狂,你甚至可以使用它搭建一個靜態頁面生成器。Gulp真的足夠強大,但你必須學會駕馭它。
這是這篇文章的主要目的。幫助你瞭解Gulp的基礎用法,助你早日完成一統天下的大業。
在我們深入瞭解之前,我們先來說說為什麼是Gulp。
為什麼是Gulp?
類似Gulp的工具,我們通常稱之為構建工具。如今最流行的兩個構建工具是Gulp和Grunt。
已經有非常多的文章論證它們之前的異同,你隨便搜一下就知道了。
主要區別是你如何使用他們構建自動化工作流。與Grunt相比,Gulp更加簡潔,執行效率更高。
讓我們繼續學習Gulp並搭建一個簡單的工作流。
我們將要做的
這篇文章的最後,你會擁有簡單的一個工作流:
- 搭建本地web伺服器
- 編譯Sass
- 每當儲存更改,自動重新整理瀏覽器
- 優化&壓縮資源
除此之外,你還將學會使用簡單命令鏈式呼叫多個任務。
安裝Gulp
安裝Gulp之前你需要先安裝Node.js。
如果你還沒安裝Node,你可以在 這裡 下載。
安裝完Node.js,使用Terminal(終端,win下是cmd)用下面命令安裝Gulp
$ sudo npm install gulp -g
只有mac使用者才需要sudo命令,並且不要把$符號也複製進去,這不是你的菜。
npm install
是指定從Node Package Manager(npm 你怕毛)安裝的命令。
-g
表示全域性安裝,這樣你在電腦上任何位置都能只用gulp 命令。
Mac 使用者需要管理員許可權才能全域性安裝,所以需要sudo。
接下來使用Gulp建立專案。
建立Gulp專案
首先,我們新建一個project資料夾,並在該目錄下執行 npm init
命令:
$ npm init
npm init命令會為你建立一個package.json檔案,這個檔案儲存著這個專案相關資訊。比如你用到的各種依賴(這裡主要是外掛)(終端會自動出現下面內容,這裡先隨便填就行)
建立完之後,我們執行下面的命令:
$ npm install gulp --save-dev
這一次,我們區域性安裝Gulp。使用—save-dev,將通知計算機在package.json中新增gulp依賴。
執行完之後,gulp將建立node_modules資料夾,裡面有個gulp資料夾。
在正式開始之前,我們再來明確下專案的目錄結構。
目錄結構
Gulp非常之靈活,理解它的內部工作,你就能在專案中得心應手。
這篇文章,我們使用通用的webapp目錄結構:
在這個結構中,我們使用app資料夾作為開發目錄(所有的原始檔都放在這下面),dist資料夾用來存放生產環境下的內容。
這些檔名,你想怎麼起都行,但請務必記住你的目錄結構。現在我們來建立gulpfile.js。
第一個Gulp任務
(你需要先在根目錄下建立一個gulpfile.js檔案)。
var gulp = require('gulp');
這行命令告知Node去node_modules中查詢gulp包,先區域性查詢,找不到就去全域性環境中查詢。找到之後就會賦值給gulp變數,然後我們就可以使用它了。
簡單的任務如下所示:
gulp.task('task-name', function() { // Stuff here });
task-name 是給你的任務起的名字,稍後在命令列中執行gulp task-name,將執行該任務。
寫個HelloWorld,是這樣的:
gulp.task('hello', function() { console.log('Hello World!'); });
命令列中執行:
$ gulp hello
那麼將會輸出Hello World!。 夠簡單吧?
Gulp任務通常都會比這難一丁點,就一丁點。通常會包含兩個特定的Gulp方法和一些列Gulp外掛。
大概這樣:
gulp.task('task-name', function () { return gulp.src('source-files') // Get source files with gulp.src .pipe(aGulpPlugin()) // Sends it through a gulp plugin .pipe(gulp.dest('destination')) // Outputs the file in the destination folder })
正如你所見,兩個Gulp方法,src,dest,一進一出[捂臉.jpg]。下面用編譯Sass來舉栗子。
Gulp執行預處理
我們使用gulp-sass外掛來編譯Sass。安裝外掛的步驟是這樣的:
-
使用npm install 命令安裝
$ npm install gulp-sass --save-dev
-
在gulpfile中引入外掛,用變數儲存
var gulp = require('gulp'); // Requires the gulp-sass plugin var sass = require('gulp-sass');
-
在任務中使用
gulp.task('sass', function(){ return gulp.src('source-files') .pipe(sass()) // Using gulp-sass .pipe(gulp.dest('destination')) });
我們需要給sass任務提供原始檔和輸出位置。所以我們先在專案中建立app/scss資料夾,裡面有個styles.scss檔案。這個檔案將在gulp.src中用到。
sass處理之後,我們希望它生成css檔案併產出到app/css目錄下,可以這樣寫:
gulp.task('sass', function(){ return gulp.src('app/scss/styles.scss') .pipe(sass()) // Converts Sass to CSS with gulp-sass .pipe(gulp.dest('app/css')) });
測試一下:
// styles.scss .testing { width: percentage(5/7); }
使用Terminal執行gulp sass,你將看到app/css/styles.css檔案下會有下面的程式碼:
/* styles.css */ .testing { width: 71.42857%; }
styles.css是gulp智動為我們生成的。percentage 是Sass的方法。
使用Sass就這麼簡單。但是通常我們不止有一個scss檔案。這時候可以使用Node萬用字元。
Node中的萬用字元
萬用字元是一種匹配模式,允許你匹配到多個檔案。不止是Node,很多平臺都有,有點像正則表示式。
使用萬用字元,計算機檢查檔名和路徑進行匹配。
大部分時候,我們只需要用到下面4種匹配模式:
*.scss
:*
號匹配當前目錄任意檔案,所以這裡*.scss
匹配當前目錄下所有scss檔案**/*.scss
:匹配當前目錄及其子目錄下的所有scss檔案。!not-me.scss
:!號移除匹配的檔案,這裡將移除not-me.scss*.+(scss|sass)
:+號後面會跟著圓括號,裡面的元素用|分割,匹配多個選項。這裡將匹配scss和sass檔案。
那麼還是上面的栗子,改造一下:
gulp.task('sass', function() { return gulp.src('app/scss/**/*.scss') // Gets all files ending with .scss in app/scss and children dirs .pipe(sass()) .pipe(gulp.dest('app/css')) })
任何app下的scss檔案,在執行命令之後將生成對應的css檔案存放到相應路徑。(智動…)
現在我們能處理多個檔案了,但是不想每次都要執行命令,怎麼辦?Gulp就是為懶人而生的,我們可以使用watch命令,自動檢測並執行。
監聽Sass檔案
Gulp提供watch方法給我們,語法如下:
// Gulp watch syntax gulp.watch('files-to-watch', ['tasks', 'to', 'run']);
將上面的栗子再改下:
// Gulp watch syntax gulp.watch('app/scss/**/*.scss', ['sass']);
通常我們監聽的還不只是一個檔案,把它變成一個任務:
gulp.task('watch', function(){ gulp.watch('app/scss/**/*.scss', ['sass']); // Other watchers })
執行gulp watch命令。
有了監聽,每次修改檔案,Gulp都將自動為我們執行任務。
還不夠,修改完直接幫我重新整理瀏覽器行嗎,我不想每次都要手動按Command + R;
使用Browser Sync自動重新整理
Browser Sync 幫助我們搭建簡單的本地伺服器並能實時重新整理瀏覽器,它還能 同時重新整理多個裝置
新外掛?記住!安裝,引入,使用。
$ npm install browser-sync --save-dev
這裡沒有gulp-字首,因為browser-sync支援Gulp,所以沒有人專門去搞一個給Gulp用。
var browserSync = require('browser-sync');
我們建立一個broswerSync任務,我們需要告知它,根目錄在哪裡。
gulp.task('browserSync', function() { browserSync({ server: { baseDir: 'app' }, }) })
我們稍微修改一下之前的程式碼,讓每次css檔案更改都重新整理一下瀏覽器:
gulp.task('sass', function() { return gulp.src('app/scss/**/*.scss') // Gets all files ending with .scss in app/scss .pipe(sass()) .pipe(gulp.dest('app/css')) .pipe(browserSync.reload({ stream: true })) });
現在我們配置好Broswer Sync了,我們需要執行這兩個命令。
我們可以在watch任務之前告知Gulp,先把browserSync和Sass任務執行了再說。
語法如下:
gulp.task('watch', ['array', 'of', 'tasks', 'to', 'complete','before', 'watch'], function (){ // ... })
應用下來是這樣:
gulp.task('watch', ['browserSync', 'sass'], function (){ gulp.watch('app/scss/**/*.scss', ['sass']); // Other watchers })
現在你執行gulp watch命令,在執行完browserSync和Sass,才會開始監聽。
並且現在瀏覽器的顯示的頁面為app/index.html。你修改了styles.scss之後,瀏覽器將自動屬性頁面。
不止是scss修改的時候需要重新整理瀏覽器吧?再改改:
gulp.task('watch', ['browserSync', 'sass'], function (){ gulp.watch('app/scss/**/*.scss', ['sass']); // Reloads the browser whenever HTML or JS files change gulp.watch('app/*.html', browserSync.reload); gulp.watch('app/js/**/*.js', browserSync.reload); });
到目前為止,我們做了下面三件事:
- 可運轉的web開發服務
- 使用Sass前處理器
- 自動重新整理瀏覽器
接下來說說優化方面的技巧
優化CSS和JavaScript檔案
說到優化的時候,我們需要想到:壓縮,拼接。也就是減少體積和HTTP次數。
開發者面臨的主要問題是很難按照正確的順序合併檔案。
<body> <!-- other stuff --> <script src="js/lib/a-library.js"></script> <script src="js/lib/another-library.js"></script> <script src="js/main.js"></script> </body>
gulp-useref會將多個檔案拼接成單一檔案,並輸出到相應目錄。
<!-- build:<type> <path> --> ... HTML Markup, list of script / link tags. <!-- endbuild -->
可以是js,css,或者remove。如果你設為remove,Gulp將不會生成檔案。
指定產出路徑。
我們想最終產出main.min.js。可以這樣寫:
<!--build:js js/main.min.js --> <script src="js/lib/a-library.js"></script> <script src="js/lib/another-library.js"></script> <script src="js/main.js"></script> <!-- endbuild -->
我們來安裝gulp-useref。
$ npm install gulp-useref --save-dev
引用
var useref = require('gulp-useref');
使用起來非常簡單:
gulp.task('useref', function(){ return gulp.src('app/*.html') .pipe(useref()) .pipe(gulp.dest('dist')); });
(新版的gulp-useref已經不需要寫多餘的useref.assets了)
執行useref命令,Gulp將合併三個script標籤成一個檔案,並儲存到dist/js/main.min.js。
合併完之後,我們再來壓縮。使用gulp-uglify外掛。
安裝
$ npm install gulp-uglify --save-dev
使用
// Other requires... var uglify = require('gulp-uglify'); gulp.task('useref', function(){ return gulp.src('app/*.html') .pipe(uglify()) // Uglifies Javascript files .pipe(useref()) .pipe(gulp.dest('dist')) });
搞定!
注意:執行完useref後,html中的script路徑將只剩下main.min.js。
王祖藍:完美~
gulp-useref同樣可以用在css上。除了壓縮,需要區分,其它內容同js一樣。所以我們使用gulp-if來做不同處理。
使用gulp-minify-css壓縮css。
$ npm install gulp-if gulp-minify-css --save-dev
應用
var gulpIf = require('gulp-if'); var minifyCSS = require('gulp-minify-css'); gulp.task('useref', function(){ return gulp.src('app/*.html') // Minifies only if it's a CSS file .pipe(gulpIf('*.css', minifyCSS())) // Uglifies only if it's a Javascript file .pipe(gulpIf('*.js', uglify())) .pipe(useref()) .pipe(gulp.dest('dist')) });
搞定!
再說說如何壓縮圖片。同樣easy。
優化圖片
使用gulp-imagemin外掛。
$ npm install gulp-imagemin --save-dev
引入,使用
var imagemin = require('gulp-imagemin'); gulp.task('images', function(){ return gulp.src('app/images/**/*.+(png|jpg|gif|svg)') .pipe(imagemin()) .pipe(gulp.dest('dist/images')) });
(所有的gulp外掛都是有相關引數可以配置,如果需要,請自行檢視。)
壓縮圖片可能會佔用較長時間,使用 gulp-cache 外掛可以減少重複壓縮。
$ npm install gulp-cache --save-dev
引入、使用
var cache = require('gulp-cache'); gulp.task('images', function(){ return gulp.src('app/images/**/*.+(png|jpg|jpeg|gif|svg)') // Caching images that ran through imagemin .pipe(cache(imagemin({ interlaced: true }))) .pipe(gulp.dest('dist/images')) });
接下來,我們說說釋出流程。
清理生成檔案
由於我們是自動生成檔案,我們不想舊檔案摻雜進來。
使用 del
npm install del --save-dev
引入、使用
var del = require('del'); gulp.task('clean', function() { del('dist'); });
但是我們又不想圖片被刪除(圖片改動的機率不大),啟用新的任務。
gulp.task('clean:dist', function(callback){ del(['dist/**/*', '!dist/images', '!dist/images/**/*'], callback) });
這個任務會刪除,除了images/資料夾,dist下的任意檔案。為了知道clean:dist任務什麼時候完成,我們需要提供callback引數。
在某些時候我們還是需要清除圖片,所以clean任務我們還需要保留。
gulp.task('clean', function(callback) { del('dist'); return cache.clearAll(callback); })
噢,我真的是廢話太多了。把我們學到的組合到一塊吧!
組合Gulp任務
廢話了這麼多,我們主要有兩條線路。
第一條是開發過程,我們便以Sass,監聽檔案,重新整理瀏覽器。
第二條是優化,我們優化CSS,JavaScript,壓縮圖片,並把資源從app移動到dist。
開發任務我們上面的watch已經組裝好了。
gulp.task('watch', ['browserSync', 'sass'], function (){ // ... watchers })
我們也做一個來執行第二條線路。
gulp.task('build', [`clean`, `sass`, `useref`, `images`, `fonts`], function (){ console.log('Building files'); })
但是這樣Gulp會同時觸發 []
的事件。我們要讓clean在其他任務之前完成。
$ npm install run-sequence --save-dev
用法如下:
var runSequence = require('run-sequence'); gulp.task('task-name', function(callback) { runSequence('task-one', 'task-two', 'task-three', callback); });
執行task-name時,Gulp會按照順序執行task-one,task-two,task-thre。
RunSequence也允許你同時執行多個任務。
gulp.task('task-name', function(callback) { runSequence('task-one', ['tasks','two','run','in','parallel'], 'task-three', callback); });
改造我們的程式碼:
gulp.task('build', function (callback) { runSequence('clean:dist', ['sass', 'useref', 'images', 'fonts'], callback ) })
開發任務我們也用runSequence:
gulp.task('default', function (callback) { runSequence(['sass','browserSync', 'watch'], callback ) })
default? 如果你的任務名字叫做default,那麼只需要輸入gulp命令即可執行。
這裡是我們最終的 程式碼倉庫 。
總結
上面的的內容搭建了一個基本的Gulp工作流。還有更精彩的內容等著你去開發。這裡提供些外掛:
開發過程:
優化:
除了開發和優化過程,你可以使用gulp-jasmine寫JavaScript單元測試,甚至使用gulp-rync直接部署dist檔案到生產環境。
譯者的話
花了點時間去學習Gulp,這篇文章是我找到比較全面的,非常適合新手入門。
Gulp其實非常簡單,多玩一下,你就能完全掌握它了,有能力的話,可以嘗試開發Gulp外掛。