一篇遲到的gulp文章,代碼合並壓縮,less編譯


前言

這篇文章本應該在去年17年寫的,但因為種種原因沒有寫,其實主要是因為懶(捂臉)。gulp出來的時間已經很早了,16年的時候還很流行,到17年就被webpack
碾壓下去了,不過由於本人接觸gulp的時候比較晚,16年的時候才聽說有這么個玩意,正真用它是在17年的時候,但是雖然現在webpack已經大行其道,我們每個人都
在積極去擁抱它,不過gulp在現在來說也並不是一無是處,還是有用到的地方,所以,這篇文章我覺得還有有必要寫的,就當做是為gulp寫的最后一篇文章吧 ,做技術就是
這么辛苦,技術更新太快,2,3年的時間就要換一撥技術,又得學習新的東西,不然面對這么激烈的市場,就得被淘汰。廢話不多說了,下面開始正文。

gulp是什么,能做什么

gulp是一個前端自動化流程構建工具,諸如,css,js,圖片合並壓縮,less,sass編譯,以前我們需要手工才能完成的工作,現在只要通過gulp並結合gulp插件就可以輕松的處理這些操作,極大的節省了開發時間,優化開發流程,提供生產效率。它跟gruntjs相比,gulpjs無需寫一大堆繁雜的配置參數,提供的API非常簡單,學習起來也很容易,另外,gulp是基於nodejs,是通過stream流的形式來讀取和操作數據,速度方面更快。

gulp API

1、gulp.src()
輸出(Emits)符合所提供的匹配模式(glob)或者匹配模式的數組(array of globs)的文件。 將返回一個 Vinyl files 的 stream 它可以被 piped 到別的插件中。

gulp.src('client/templates/*.jade')
  .pipe(jade())
  .pipe(minify())
  .pipe(gulp.dest('build/minified_templates'));

2、gulp.dest()
能被 pipe 進來,並且將會寫文件。並且重新輸出(emits)所有數據,因此你可以將它 pipe 到多個文件夾。如果某文件夾不存在,將會自動創建它。

gulp.src('./client/templates/*.jade')
  .pipe(jade())
  .pipe(gulp.dest('./build/templates'))
  .pipe(minify())
  .pipe(gulp.dest('./build/minified_templates'));

3、gulp.task()
定義一個使用 Orchestrator 實現的任務(task)。

gulp.task('somename', function() {
  // 做一些事
});

4、gulp.watch()
監視文件,並且可以在文件發生改動時候做一些事情。它總會返回一個 EventEmitter 來發射(emit) change 事件。

var watcher = gulp.watch('js/**/*.js', ['uglify','reload']);
watcher.on('change', function(event) {
  console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
});

整理的一些gulp插件

一、必備插件,一些基礎插件

gulp-htmlmin 看到名字就能知道,這個插件是用來壓縮 HTML。PS:注釋啥的都可以去掉哦,看文檔get更多技能哈
gulp-imagemin 除了能壓縮常見的圖片格式,還能壓縮 SVG,叼叼的~
gulp-clean-css 壓縮 CSS。我原本推薦的是 gulp-minify-css,結果其首頁中已建議改用gulp-clean-css...
gulp-uglify 專業壓縮 Javascript
gulp-concat 上面幾個都是壓縮,這插件是管合並的...恭喜,“減少網絡請求”的成就達成:)
gulp-autoprefixer 給 CSS 增加前綴。解決某些CSS屬性不是標准屬性,有各種瀏覽器前綴的情況,灰常有用
gulp-rename 修改文件名稱。比如有時我們需要把app.js改成app.min.js,瞬間高級了
gulp-util 最基礎的工具,但俺只用來打日志...

二、常用插件,一些有用的插件,但使用場景和頻率沒那么高的好插件

run-sequence gulp 的 task 都是並行(異步)執行,如果遇見需要串行的場景,那么這個插件就是必備了。偶的使用場景是:處理(壓縮、合並等等) CSS/JS、再gulp-rev、再上傳 CDN;然后使用 CDN的地址替換 HTML 中的 CSS/JS 地址,再壓縮 HTML。那么替換 HTML 這步須在之前的工作處理完后再執行。 ** 最后要說,gulp4.0發布后,不需要RS也可以搞定串行任務了 **
del / gulp-clean 刪除。俺的使用場景是:JS/CSS 文件都會在壓縮后使用gulp-rev,即文件名被hash,然后再上傳到 CDN,最后俺再使用 刪除插件 把本地壓縮后的文件刪除掉,不用多余保存。
gulp-rev 把靜態文件名改成hash的形式。
gulp-rev-replace 配合 gulp-rev 使用,拿到生成的 manifest。json 后替換對應的文件名稱。
gulp-rev-collector 到線上環境前,我會用來配合gulp-rev使用,替換 HTML 中的路徑
gulp-rev-append 給頁面引用的靜態文件增加hash后綴,避免被瀏覽器緩存...當然,如果是使用 CDN,這個套路就不行了
gulp-connect / gulp-livereload LiveReload 的倆款插件都值得擁有,不過都各稍有學習成本,看看文檔就明白鳥
gulp-sourcemaps 處理 JavaScript 時生成 SourceMap;如果你不了解 SourceMap,可以看看這篇阮一峰大神的《Source Map 詳解》
gulp-load-plugins 幫忙偷懶用的,可以幫我們加載插件,不用require或者import...當然,俺個人感覺用了這個插件后,閱讀gulpfile.js的可讀性差了,魚和熊掌不可兼得:(
gulp-jshint JavaScript 代碼校驗
gulp-sass / gulp-less 寫 CSS 的同學都懂哈

三、進階插件,根據業務場景的不同,我們可能會用到這些插件

babel JS 語法新特性用起來。這個插件可以讓我們用新的 標准/特性/提案 寫 JavaScript 代碼,然后再向下 轉換編譯,最終生成隨處可用的 JavaScript 代碼。更通俗的說話就是:可以用新的規范寫代碼,經過 babel 編譯后生成沒有兼容問題的代碼。
gulp-flatten 移動指定文件,不想壓縮或者合並的時候,直接用這個插件把對應文件移動到指定文件夾。俺偶爾在內部項目會偷懶用上,圖方便:)
gulp-coffee CoffeeScript 值得去了解
gulp-markdown-pdf 把 Markdown 編譯為 PDF
gulp-markdown 寫手的福音,可以把 Markdown 轉成 HTML
gulp-html2md 把 HTML 編譯為 Markdown
gulp-tinypng 超屌的圖片壓縮工具,使用 Tinypng 引擎。PS:因為 Tinypng 免費帳號有月限制,所以使用使需注意。
sprity 生成雪碧圖。稍有點學習成本,仔細閱讀文檔即可。
gulp-if 可以在 pipe 里面寫點邏輯了,屌不屌。舉例:比如處理 ./pub/*.js,如果文件名稱是 xxx.js,那么不處理;更可以用來區分當前是開發環境還是生產環境。
gulp-file-include 俺搞內部項目的時候會用到,讓 HTML 組件化的第一小步
gulp-git 直接在 Build 時把代碼都提交到 git上了...特么勞資懶起來連我自己都害怕
gulp-qiniu 用於把指定文件上傳至七牛的指定路徑下(PS:首先,你得有自己的七牛賬號和空間)
gulp-notify 在控制台中加入文字描述,build 的時候更高級有木有。當然,當需要的時候把錯誤信息也展示出來會很有幫助。更高級的功能就需要你查看其文檔了~
gulp-plumber gulp 的錯誤處理有點坑,假如發生錯誤進程就掛了。相對的解決辦法不少,但是這個是我個人比較推薦的,比特么在容易出錯的地方寫錯誤監聽靠譜。所以這個插件可以阻止 gulp 插件發生錯誤導致進程退出並輸出錯誤日志。

gulp的使用

1、在項目根目錄下創建一個名為 gulpfile.js 的文件

var gulp = require('gulp');
gulp.task('default', function() {
     console.log("執行第一個gulp任務")
});

輸入gulp命令執行該任務,不指定任務名稱 則默認執行default任務

2、同時執行多個任務

gulp.task('n1',function(){
	console.log("執行任務n1")
});
gulp.task('n2',function(){
	console.log("執行任務n2")
});
gulp.task('N',['n1','n2']);

3、如果有2個任務存在依賴關系,如任務A依賴任務B,在B任務執行完成之后再執行A任務

gulp.task('B',function(){
	console.log("執行任務B")
});
gulp.task('A',['B'],function(){
	console.log("任務B執行完成之后,開始執行任務A")
});

4、通過gulp.watch監聽文件變化,這里新建一個watch task任務,用gulp.watch來監聽index.html文件,執行該task任務

gulp.task('watch',function(){
	gulp.watch('./src/index.html').on('change', function(event) {
	  console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
	});
});

修改index.html文件,可以看到控制台輸出以下內容,event.type輸出的是changed,除此之外還有added, deleted類型

5、編譯less
這里使用gulp-less插件

安裝  npm install --save-dev gulp-less

var less = require("gulp-less");
gulp.task('less',function(){
	console.log("開始編譯less...")
	gulp.src('./src/less/index.less')
		.pipe(less())
		.pipe(gulp.dest('./src/css'));
	console.log("less編譯完成");
});


可以看到自動為我們生成了一個index同名css文件

使用gulp-postcss和autoprefixer 插件處理瀏覽器前綴,解決瀏覽器兼容性問題,不必手動添加css前綴,並且支持soucemap

安裝
npm install gulp-postcss --save-dev
npm install autoprefixer --save-dev
npm install gulp-sourcemaps --save-dev 

var less = require("gulp-less");
var postcss = require('gulp-postcss');
var sourcemaps   = require('gulp-sourcemaps');
var autoprefixer = require('autoprefixer');
gulp.task('less',function(){
	console.log("開始編譯less...")
	gulp.src('./src/less/index.less')
		.pipe(less())
		.pipe(sourcemaps.init())
		.pipe(postcss([autoprefixer()]))
		.pipe(sourcemaps.write('.'))
		.pipe(gulp.dest('./src/css'));
	console.log("less編譯完成");
});

修改less文件添加以下樣式:

.win{transform: translateX(-50%);}

執行編譯less任務,可以看到index.css文件自動為transform添加了瀏覽器前綴


同時也為我們生成了一個map格式文件

6、watch監聽less文件變化,自動執行less編譯任務

gulp.task('watch',function(){
	gulp.watch(['./src/less/index.less'],['less']);
});

當修改less文件並保存時,看到less文件已經編譯完成了

7、使用broswer-sync自動刷新瀏覽器

安裝
npm install browser-sync --save-dev
// 靜態服務器 + 監聽 less/html 文件
var browserSync = require('browser-sync').create();
gulp.task('browser-sync',['less'],function(){
	browserSync.init({
        server: {
            baseDir: "./src"   // 從這個項目的src目錄啟動服務器
        }
    });
    gulp.watch(['./src/less/index.less'],['less']);//監聽less文件
    gulp.watch("src/*.html").on('change', browserSync.reload);//監聽html文件變化 自動刷新瀏覽器
});

最后,修改html文件並保存,可以看到瀏覽器自動刷新了
less+css瀏覽器注入
在less任務后面添加以下代碼,將less編譯后的css注入到瀏覽器里實現更新,換句話說就是我們修改less文件后編譯完成后的css反應到瀏覽器頁面中
.pipe(browserSync.reload({stream: true}));
添加以上代碼后,但發現還是無法實現刷新 ,這里如果我們編譯less使用了sourcemap,則無法刷新,可以通過gulp-filter來解決。

安裝:
npm install gulp-filter --save-dev

修改編譯less的任務,添加紅色部分內容即可

8、使用gulp-clean-css壓縮css文件並重命名

安裝:
npm install gulp-clean-css --save-dev
npm install gulp-rename --save-dev

// 壓縮css文件並重命名
var cleanCSS = require('gulp-clean-css');
var rename = require("gulp-rename");
gulp.task('minify-css',function(){
	gulp.src('./src/css/*.css')
		.pipe(rename({suffix: '.min'})) //suffix添加后綴   其他的還有prefix , extname等
		.pipe(cleanCSS())
		.pipe(gulp.dest('./src/css'));
});

執行該task,可以看到生成了index.min.css壓縮文件

9、為我們的css文件MD5命名 並且在引用的文件路徑替換
主要用到 gulp-rev 和gulp-rev-collector這兩個插件

安裝
npm install gulp-rev --save-dev
npm install gulp-rev-collector --save-dev

// 壓縮css文件並重命名
// md5文件命名  引用路徑替換
var cleanCSS = require('gulp-clean-css');
var rename = require("gulp-rename");
var rev = require('gulp-rev');         //- 對文件名加MD5后綴
var revCollector = require('gulp-rev-collector');               //- 路徑替換
gulp.task('minify-css',function(){
	console.log('開始壓縮css文件')
	return gulp.src('./src/css/*.css')
		.pipe(rename({suffix:'.min'})) //文件重命名  suffix添加后綴   其他的還有prefix , extname等
		.pipe(cleanCSS())   //壓縮處理
		.pipe(rev())         //- 文件名加MD5后綴
		.pipe(gulp.dest('./src/css'))  //- 輸出文件本地
		.pipe(rev.manifest())          //- 生成一個rev-manifest.json    后面的文件路徑替換依據此文件內容
		.pipe(gulp.dest('./rev'));      //- 將 rev-manifest.json 保存到 rev 目錄內
	console.log('css壓縮完成...')
});

gulp運行 minify-css任務,可以看到生成了md5命名的css壓縮文件

執行壓縮之前先刪除文件
del和gulp-clean插件 都是用於清空文件,del可以用於替代gulp-clean,不推薦使用gulp-clean了

安裝
npm install del --save-dev

// clean任務:在執行壓縮之前先clean
var del  = require('del');
gulp.task('clean',function(cb){
  return del(['./dist']);
})

10、使用gulp-sequence插件處理同步任務
run-sequence gulp 的 task 都是並行(異步)執行,如果遇見需要串行的場景,那么這個插件就是必備了。偶的使用場景是:處理(壓縮、合並等等) CSS/JS、再gulp-rev、再上傳 CDN;然后使用 CDN的地址替換 HTML 中的 CSS/JS 地址,再壓縮 HTML。那么替換 HTML 這步須在之前的工作處理完后再執行。 ** 最后要說,gulp4.0發布后,不需要RS也可以搞定串行任務了 **

執行前端代碼自動構建,一般會分為以下幾個步驟
1. 清理目標目錄(任務:clean)
2. 代碼壓縮打包,這其中包括對JS,CSS,HTML以及圖片的處理(任務:minify:js,minify:css,minify:html,minify:image)
3. 監控(任務:watch)

安裝
npm install --save-dev run-sequence

// 同步執行任務
var runSequence = require('run-sequence');
gulp.task('build', function() {
  runSequence('rev');
});

11、javascript代碼壓縮
gulp-uglify

安裝
npm install gulp-uglify --save-dev
var uglify = require('gulp-uglify'); 
gulp.task('minify-js',function(){
	 gulp.src('src/js/*.js')
	 	.pipe(uglify())  
	 	.pipe(gulp.dest('dist/js'));
});

壓縮之后代碼:

12、html代碼壓縮
gulp-htmlmin

安裝
npm install gulp-htmlmin --save-dev
var htmlmin = require('gulp-htmlmin');
gulp.task('minify-html', function() {
  return gulp.src('src/*.html')
    .pipe(htmlmin({collapseWhitespace: true}))
    .pipe(gulp.dest('dist'));
});

壓縮之后代碼:

13、圖片壓縮(包括PNG、JPEG、GIF和SVG圖片)
gulp-imagemin

安裝
npm install gulp-imagemin --save-dev
gulp.task('minify-img', function() {
  return gulp.src('src/images/*.{png,jpg,gif,ico}')
    .pipe(imagemin())
    .pipe(gulp.dest('dist/images'));
});

壓縮之前大小

壓縮之后大小

其他參數

var imagemin = require('gulp-imagemin');
gulp.task('minify-img', function() {
  return gulp.src('src/images/*.{png,jpg,gif,ico}')
    .pipe(imagemin({
            optimizationLevel: 5, //類型:Number  默認:3  取值范圍:0-7(優化等級)
            progressive: true, //類型:Boolean 默認:false 無損壓縮jpg圖片
            interlaced: true, //類型:Boolean 默認:false 隔行掃描gif進行渲染
            multipass: true //類型:Boolean 默認:false 多次優化svg直到完全優化
        }))
    .pipe(gulp.dest('dist/images'));
});

14、js代碼合並,減少http請求數量
gulp-concat

安裝
npm install gulp-concat --save-dev
var concat = require('gulp-concat');
gulp.task('jsconcat', function () {
    gulp.src('src/js/*.js')
        .pipe(concat('main.js'))//合並后的文件名
        .pipe(gulp.dest('dist/js'));
});

坑記錄

1、在編寫less文件時報以下這個錯誤,發現是因為我sublime安裝了less2css這個插件

首選項-》pageage setting找到less2css,發現default設置autocompile是true自動編譯
修改user設置將autoCompile設置為false即可

{
  "autoCompile": true
}

2、在壓縮css文件時,生成格式有問題

在壓縮之前先清空目標文件

3、關於gulp的gulp-clean-css壓縮插件參數問題

這是告訴cleancss壓縮時要不要保留IE8及以下兼容寫法,寫compatibility:'ie7'就是保留ie7兼容寫法。。比如zoom:1;這些,不保留它就給你刪除了。。
壓縮插件不僅僅是壓縮,還能優化,如果你用gulp-cssnano,還能幫你把多余的類名和屬性合並。。等等

4、gulp中的return
在gulp這里,返回的是gulp.src這個對象,以便接下來的回調(如果有的話)能繼續調用這個gulp.src對象,完成其他的事情。

task的回調函數必須得有返回值
return a promise or event stream。否則程序就相當於同步的
當任務有返回以上返回值時,則任務會按一定的順序執行。

5.在開啟靜態服務器模式下,監聽文件變化,如果執行clean刪除任務會報以下錯誤

在開發環境,靜態服務器模式下,不要執行clean任務

6、gulp.watch監聽

gulp.task('watch',function(){
    gulp.watch('./stylesheets/**/*.scss',['sass']);
})

以上代碼,**是指所有深度的文件夾,包括varible和mixin

最后

總結一下,本文從gulp是什么,gulp能做什么出發,對gulp簡單的介紹了一下,包括gulp提供的一些API,然后整理並羅列了一些開發中常用到的gulp插件,
最后,就是從gulp安裝到使用詳細介紹了gulp的用法,以及使用gulp插件來構建前端自動化的開發流程。

以上在介紹gulp的使用時,我也准備了一個gulp的demo,demo代碼我已經上傳到github中,大家可以自行下載。另外,我建立了一個gulp自動化構建工程模板,支持less編譯,html、css、js文件及圖片壓縮,自動添加瀏覽器前綴,本地開發環境下文件監聽瀏覽器自動刷新等,不需要再重新搭建gulp工程,就可以輕松構建你的前端gulp自動化工作流程,代碼已上傳到github,地址https://github.com/fozero/template-gulp,如果喜歡的話,歡迎star哦~ ,如有問題也可以在上面提issues

相關資料

https://www.gulpjs.com.cn/
https://www.cnblogs.com/2050/p/4198792.html
https://www.cnblogs.com/Darren_code/p/gulp.html
https://www.cnblogs.com/2050/p/4198792.html
https://blog.csdn.net/mjzhang1993/article/details/68485085

作者:fozero
聲明:原創文章,轉載請注明出處,謝謝!http://www.cnblogs.com/fozero/p/8994464.html
標簽:gulp


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM