關於什么是gulp,它和grunt有什么區別等問題,這里不做任何介紹。本文主要介紹如何使用gulp-usemin這款插件,同時也會簡單介紹本文中用到的一些插件。
什么是gulp-usemin
用來將HTML 文件中(或者templates/views)中沒有優化的script 和stylesheets 替換為優化過的版本
gulp-usemin根據預先在html文件(或者其它模板/視圖中的文件)中聲明好的blocks來執行一系列任務(例如合並文件並重全名、排除一些只在開發過程中引入的腳本以及將css和js中的代碼提取出來內嵌在html文件中)來處理未優化的樣式和腳本。然后我們可以通過gulp.dest()
方法將處理的結果輸出到其它目錄。
如何使用
首先需要了解在html中如何聲明一個blocks,一個blocks定義如下:
<!-- build:<pipelineId>(alternate search path) <path> -->
... HTML Markup, list of script / link tags.
<!-- endbuild -->
```
- pipelineId:在配置文件中需要使用的 pipeline id 或者 指定 remove 聲明用於移除整塊blocks
- alternate search path:(可選項)默認情況下任務讀取的輸入文件相對於blocks塊中引入的路徑,使用這一可選配置項可以修改文件引入的路徑
- path:最終合並和處理后輸出的文件名及路徑
這里使用gulp-usemin文檔中給出的示例目錄結構作為演示,目錄結構如下:
|
+- app
| +- index.html
| +- assets
| +- js
| +- foo.js
| +- bar.js
| +- baz.js
| +- css
| +- clear.css
| +- main.css
+- dist
+- node_modules
+- gulpfile.js
這里我們用到了下面列舉的一些gulp插件:
- gulp-load-plugins:省去手動引用插件的麻煩
- gulp-usemin:本文主要講解的插件
- gulp-uglify:壓縮js
- gulp-minify-css:壓縮css
- gulp-clean:清空目錄
- gulp-rev:添加md5戳
任務一:文件合並到指定的目錄文件名下
這是一個很常規的任務,把需要合並的文件放置在對就的blocks里面,然后指出合並后的文件對應文件名即可。下面是合並前的app/index.html
中未優化前的內容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>gulp-usemin示例</title>
<!-- build:css style.css -->
<link rel="stylesheet" href="css/clear.css"/>
<link rel="stylesheet" href="css/main.css"/>
<!-- endbuild -->
</head>
<body>
<!-- build:js js/optimized.js -->
<script src="assets/js/foo.js"></script>
<script src="assets/js/bar.js"></script>
<!-- endbuild -->
</body>
</html>
然后,在app/gulpfile.js
中給出對就的task,這里我們對合並后的css和javaScript進行了壓縮,並最終輸出到dist/
目錄下
'use strict';
var gulp = require('gulp'),
$ = require("gulp-load-plugins")();
gulp.task('usemin', function() {
return gulp.src('./app/index.html')
.pipe($.usemin({
js: [$.uglify()],
css: [$.minifyCss()]
}))
.pipe(gulp.dest('dist/'));
});
生成后的dist/
目錄如下
|
+- dist
| +- js
| +- optimized.js
| +- index.html
| +- style.css
最終在dist/index.html
只有合並過后的文件引用,同時在app/index.html
文件中的添加的blocks聲明注釋也自動去掉了。
當然這里也可以保留注釋,只需要在配置中將enableHtmlComment設置為
true`就可以了。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>gulp-usemin示例</title>
<link rel="stylesheet" href="style.css"/>
</head>
<body>
<script src="js/optimized.js"></script>
</body>
</html>
`dist/style.css為壓縮后的樣式
.clear{clear:both}.main{width:1200px;margin:0 auto}.btn{display:inline-block;text-align:center;border:none;background:#136fd2;color:#fff;border-radius:4px;box-shadow:0 -2px 0 #1360ba inset;padding:9px 10px;font-size:12px;font-weight:700;margin-bottom:4px}
dist/js/optimized.js
如下:
console.log("foo"),console.log("bar");
任務二:將樣式和腳本直接嵌入到頁面中
使用gulp-usemin不光可以合並文件,可以將指定的文件嵌入到html文件中,這功能很強大。
在開始這個任務前先把上一個任務生成的文件使用gulp-clean全部清除掉
gulp.task('clean', function() {
gulp.src('./dist/*')
.pipe($.clean());
});
接下來更改app/index.html
內容為
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>gulp-usemin示例</title>
<!-- build:inlinecss -->
<link rel="stylesheet" href="css/clear.css"/>
<link rel="stylesheet" href="css/main.css"/>
<!-- endbuild -->
</head>
<body>
<!-- build:inlinejs -->
<script src="assets/js/foo.js"></script>
<script src="assets/js/bar.js"></script>
<!-- endbuild -->
</body>
</html>
這里任務不變,最終在dist/index.html
的內容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>gulp-usemin示例</title>
<style>.clear {
clear: both;
}
.main {
width: 1200px;
margin: 0 auto;
}
.btn {
display: inline-block;
text-align: center;
border: none;
background: #136fd2;
color: white;
border-radius: 4px;
box-shadow: 0 -2px 0 #1360ba inset;
padding: 9px 10px;
font-size: 12px;
font-weight: bold;
margin-bottom: 4px;
}</style>
</head>
<body>
<script>console.log('foo');
console.log('bar');</script>
</body>
</html>
雖然我們在配置中添加了壓縮樣式和腳本的功能,但觀察生成后的文件,其實並沒有被壓縮。
任務三: 移除部分文件
這是是指最終生成的文件中不包含某些文件,比較常見的是在開發過種中手動使用 mockAjax 和 mockJSON 模擬ajax數據和請求,但在發布的時候這些文件引用需要手動刪除掉。
同樣先清空dist/
目錄,然后更改app/index.html
如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>gulp-usemin示例</title>
<!-- build:css style.css -->
<link rel="stylesheet" href="css/clear.css"/>
<link rel="stylesheet" href="css/main.css"/>
<!-- endbuild -->
</head>
<body>
<!-- build:js js/optimized.js -->
<script src="assets/js/foo.js"></script>
<script src="assets/js/bar.js"></script>
<!-- endbuild -->
<!-- build:remove -->
<script src="assets/js/baz.js"></script>
<!-- endbuild -->
</body>
</html>
這里的assets/js/baz.js
是不會被輸出到dist/js
文件中,結果如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>gulp-usemin示例</title>
<link rel="stylesheet" href="style.css"/>
</head>
<body>
<script src="js/optimized.js"></script>
</body>
</html>
任務四:為文件添加md5戳
接下來在任務一的基礎上對文件添加一個md5戳,這里使用gulp-rev插件
gulp.task('usemin', function() {
return gulp.src('./app/index.html')
.pipe($.usemin({
js: [$.uglify(), $.rev()],
css: [$.minifyCss(), $.rev()]
}))
.pipe(gulp.dest('dist/'))
});
執行后dist/index.html
如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>gulp-usemin示例</title>
<link rel="stylesheet" href="style-a28260ea41.css"/>
</head>
<body>
<script src="js/optimized-62fa5ef80a.js"></script>
</body>
</html>
生成后的dist/
目錄
|
+- dist
| +- js
| +- optimized-62fa5ef80a.js
| +- index.html
| +- style-a28260ea41.css
是不是很爽,這樣就ok了?
但還不夠完美,如果再去改一下css或者js文件,再次執行任務,會發現又生成了一個style-d4bd3b66b7.css
(名字可能不同)樣式,而且html對應的資源引用也是指向這個新生成的,同時原來的style-a28260ea41.css
文件也還一直存在,很明顯浪費了磁盤空間。那好手動刪除了吧╯﹏╰,算了,直接使用gulp-clean把整個清空,重新生成一遍,但認真一想,如果項目要生成的文件成百上千,我再生成一次太耗費時間了,其實我只想更新一部分文件。
關於這個問題在網上找了好久的解決方案,這里找到了一個gulp-rev-outdated插件,使用它可以自定義保存多少個舊版本的文件,每次更新就會刪除掉老的一個版本。其它的方案還在嘗試中。
插件中有一個cleaner()
方法,涉及到三個依賴文件gulp-util
, rimraf
和thought2
,請自行下載。
'use strict';
var gulp = require('gulp'),
path = require('path'),
through = require('through2'),
del = require('del'),
$ = require("gulp-load-plugins")();
function cleaner() {
return through.obj(function(file, enc, cb){
del(path.resolve( (file.cwd || process.cwd()), file.path)).then(function() {
this.push(file);
cb();
}, function(err) {
this.emit('error', new $.util.PluginError('Cleanup old files', err));
});
});
}
gulp.task('usemin', ['clean:rev'], function() {
return gulp.src('./app/index.html')
.pipe($.usemin({
js: [$.uglify(), $.rev()],
css: [$.minifyCss(), $.rev()]
}))
.pipe(gulp.dest('dist/'))
});
gulp.task('clean:rev', function() {
gulp.src(['dist/**/*.*'], {read: false})
.pipe( $.revOutdated(1)) // 只保存一個舊版本的rev
.pipe(cleaner())
return;
})
// 清空dist目錄下的所有文件
gulp.task('clean', function() {
gulp.src('./dist/*')
.pipe($.clean())
});
注意:由於文檔中使用的rimraf
插件gulp官方不建議使用了,所以改成了更為常用的del
插件。
運行后的dist/
目錄如下:
|
+- dist
| +- js
| +- optimized-62fa5ef80a.js
| +- index.html
| +- style-2091d1f99f.css
| +- style-fffb5ca589.css
其中`dist/index.html內容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>gulp-usemin示例</title>
<link rel="stylesheet" href="style-fffb5ca589.css"/>
</head>
<body>
<script src="js/optimized-62fa5ef80a.js"></script>
</body>
</html>
結語
注意,雖然本文介紹了gulp-usemin的使用方法,但這個插件現在已不推薦使用了,詳情可以查看gulp黑名單,官方推薦使用 gulp-useref 來達到同樣的目的。
本文示例代碼地址:https://github.com/wujie520303/blogCode/tree/master/gulp/gulp-usemin-demo