說一下前端的自動化構建工具gulp吧,其實國內的前端自動化工具比較流行的還有就是fis
和grunt
了咐刨,但是我覺得目前gulp的社區(qū)相對友好,而且關于gulp也是特別容易快速上手的
請一定要看我貼的代碼扬霜,因為許多的gulp知識我都是通過粘貼代碼附帶對應的注釋的方式講解的定鸟,這樣的話你不懂代碼就在下邊可以結合注釋講解快速入門gulp的
那么首先我們先進行全局安裝gulp
npm i -g gulp
然后我們需要在我們需要構建的項目中局部安裝一個本地開發(fā)依賴gulp
npm i -D gulp
然后我們需要新建一個用于執(zhí)行gulp任務的js文件,默認為gulpfile.js
文件
這也就是我們需要局部安裝gulp的原因畜挥,因為我們的默認gulpfile文件中需要引用到gulp這個依賴,也就是
require("gulp")
如果package.json
文件中沒有的話不就出問題了嗎?
那么其實所有的構建工具感覺上都是一樣的婴谱,如果沒有插件就沒有任何的用處蟹但,所以這里我們需要接觸到我們的第一個插件
npm install --save-dev gulp-uglify
然后我們在代碼中這樣寫
const gulp = require("gulp")
// 命名的話一般就是去掉gulp等字符,因為在這個gulpfile中一看就知道是gulp的插件啊谭羔,總不可能是webpack的loader吧
// gulp-uglify這個插件代表著壓縮js代碼
const uglify = require("gulp-uglify")
// 建議大家使用es5函數(shù)华糖,而不是箭頭函數(shù)
// task函數(shù)可以聲明一個gulp的task,那么默認gulp是以task進行工作的
// 每一部分的構建都可以細分不同的task
gulp.task("minify",function(){
// 第一個參數(shù)為task的名字瘟裸,盡量是一看名字就知道是干啥的那種
// 這里是運行這個任務的邏輯
// src函數(shù)客叉,gulp是以數(shù)據(jù)流的方式進行構建我們的代碼的
// 所以我們需要使用src函數(shù)為gulp提供一個需要待處理的輸入流數(shù)據(jù)
gulp.src("./js/01.js")
// 然后我們可以通過管道的方式讓不同的插件處理這些數(shù)據(jù)
.pipe(uglify())
// 同樣的我們需要通過管道將這些數(shù)據(jù)輸出出去
// 這里我們使用dest函數(shù)代表輸出經(jīng)過處理的src函數(shù)提供的數(shù)據(jù)流
.pipe(gulp.dest("./01.min.js"));
})
那么我們的代碼中引用了js文件夾下的所有js文件大家可以自行書寫一些js文件,那么我這里是在js文件夾下01.js
文件的內容是
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
Person.prototype = {
constructor: Person,
sayHello:function() {
console.log("name:" + this.name + "age:" + this.age + "sex:" + this.sex);
}
}
new Person("suiyue",10,"男").sayHello();
然后現(xiàn)在是不是特別的激動呢话告?我們現(xiàn)在是萬事俱備兼搏,只欠東風了,那么我們快速打開我們的cmd工具定位到當前目錄下吧沙郭,然后我們運行
gulp taskname
// 這里我們
gulp minify
執(zhí)行這個task吧佛呻,我們看看效果吧
大家一定要注意啊,這個坑爹的
uglify
是不能夠壓縮es6js語法的病线,直接報錯明白吧吓著,剛開始寫的是class
class`后面幾次報錯就改成原始寫法了,賊坑送挑,注意
然后我們就會發(fā)現(xiàn)我們的代碼已經(jīng)打包好了
那么大家還會發(fā)現(xiàn)控制臺報了一個錯誤绑莺,大致意思好像是說這個task沒有完成,需要異步執(zhí)行惕耕,這里就有兩種解決辦法了纺裁,我們可以直接給task后面的函數(shù)加上
async
關鍵字
完美解決,第二種就是可以給task后面的邏輯處理函數(shù)接受一個可選的done回調主動告訴gulp任務完成
同樣的可以完美解決司澎,但是還是建議大家使用async關鍵字对扶,使用異步函數(shù)解決此問題区赵,異步就是不可控性,其實你并不知道他什么時候就能夠執(zhí)行完成浪南,所以有些時候根本不知道什么時候回調done函數(shù)笼才,請大家選擇第一種方式
關于第一個插件gulp-uglify就說到此,接下來說一說gulp上面的babel插件络凿,不然的話高階語法根本無法丑陋化骡送,你懂我的意思吧
-
gulp-babel
關于gulp-babel就是gulp調用babel模塊轉換js語法而已,其實本質上是一樣的絮记,那么我們首先安裝項目依賴摔踱,這里推薦大家使用babel7,所以直奔babel7了怨愤,而且babel7配置相對babel6要簡單的多
npm install --save-dev gulp-babel @babel/core @babel/preset-env
然后我們立馬給gulp下達一個任務吧派敷,配置好任務
const gulp = require("gulp")
// 壓縮js代碼插件
const uglify = require("gulp-uglify")
// babel插件
const babel = require("gulp-babel")
// 壓縮js代碼任務
gulp.task("minify", async function () {
gulp.src("./js/01.js")
.pipe(uglify())
.pipe(gulp.dest("./01.min.js"));
})
gulp.task("tfSyntax",async function(){
gulp.src("js/*.js")
.pipe(babel({
// 相當于babel配置文件
presets:["@babel/env"]
}))
.pipe(gulp.dest("dist"))
})
更改我們js的代碼為高階語法
class Person {
constructor(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
sayHello() {
console.log(`我叫${this.name}我今年${this.age}歲了我是一個小小小${this.sex}生`);
}
}
new Person("suiyue",10,"男").sayHello();
好的,我們迅速在命令行中運行
gulp tfSyntax
讓gulp跑起來撰洗,不出意外的話篮愉,那么我們就會在dist目錄下看到被轉換后的代碼,就像這樣
"use strict";
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
var Person =
/*#__PURE__*/
function () {
function Person(name, age, sex) {
_classCallCheck(this, Person);
this.name = name;
this.age = age;
this.sex = sex;
}
_createClass(Person, [{
key: "sayHello",
value: function sayHello() {
console.log("\u6211\u53EB".concat(this.name, "\u6211\u4ECA\u5E74").concat(this.age, "\u5C81\u4E86\u6211\u662F\u4E00\u4E2A\u5C0F\u5C0F\u5C0F").concat(this.sex, "\u751F"));
}
}]);
return Person;
}();
new Person("suiyue", 10, "男").sayHello();
這時候相信學到這里你就有點懵圈了差导,不是說好的自動化工具嗎试躏?我怎么感覺我轉換了高階語法還要在gulp一下
minify
這個task才能行呢?自動化不是應該什么都幫我們做了嗎设褐?這是一個什么鬼情況颠蕴?
在這里我想說的就是大家莫要慌,我們接著往下讀
然后我們說一下gulp的默認任務助析,我們現(xiàn)在是個什么情況犀被,我們現(xiàn)在就是每一次聲明一個任務然后就必須在控制臺中gulp一下任務名稱運行,那么作為自動化工具的gulp當然不會這么low外冀,你懂吧弱判?所以gulp提供了一個默認的任務讓我們直接運行gulp
就行了,請看下面
const gulp = require("gulp")
// 壓縮js代碼插件
const uglify = require("gulp-uglify")
// babel插件
const babel = require("gulp-babel")
// 這是一個坑爹的默認任務名锥惋,還要手打
gulp.task("default",async function(){
// 如果直接在命令行敲gulp昌腰,就會默認運行 default這個任務,沒有就沒有咯
console.log("123");
})
// 壓縮js代碼任務
gulp.task("minify", async function () {
gulp.src("./js/01.js")
.pipe(uglify())
.pipe(gulp.dest("./01.min.js"));
})
// 轉換高階語法任務
gulp.task("tfSyntax",async function(){
gulp.src("js/*.js")
.pipe(babel({
// 相當于babel配置文件
presets:["@babel/env"]
}))
.pipe(gulp.dest("dist"))
})
那么我們這里在default
任務中輸出123膀跌,那么我們直接在命令行中
直接gulp就行了遭商,這樣就輸出了123,大家應該懂了什么叫做默認任務了吧捅伤!
然后我們就可以進行先轉換代碼再壓縮代碼的功能了
const gulp = require("gulp")
// 壓縮js代碼插件
const uglify = require("gulp-uglify")
// babel插件
const babel = require("gulp-babel")
gulp.task("minifyJS",async ()=>{
gulp.src("js/*.js")
.pipe(babel({
presets:['@babel/env']
}))
.pipe(uglify())
.pipe(gulp.dest("dist"))
})
大家應該能夠看懂代碼了吧
大家就可以在對應的dist文件夾下看到我們轉換壓縮之后的js代碼了
但是到這時候我們還是沒有體會到gulp的自動化啊劫流,因為我們一整個項目不僅需要處理js還有css也可能需要處理html啊,到這時候我們還是沒有發(fā)現(xiàn)gulp哪里自動化了,繼續(xù)繼續(xù)繼續(xù)
-
任務的依賴
順序執(zhí)行
關于gulp任務的依賴祠汇,就是實現(xiàn)自動化的最大一特性仍秤,配合gulp的默認task可以迅速實現(xiàn)gulp的自動化
這里主要說說gulp最新版本gulp4的任務依賴,gulp3跟gulp改動還是稍微有點大的可很,還有就是目前(2019年7月13日-11點16分)gulp中文網(wǎng)的文檔還是gulp3的但是我們現(xiàn)在安裝的gulp已經(jīng)默認為gulp4了诗力,同時也推薦大家使用gulp4,因為gulp4對比gulp3優(yōu)化了很多東西
然后這里我從頭開始寫一個gulpfile出來
const gulp = require("gulp")
gulp.task("one",function(done){
console.log("one")
done()
})
gulp.task("two",function(done){
console.log("two")
done()
})
// 第一點就是這個默認的default任務一定要寫在最下邊我抠,不然后面的series任務不會被找到
gulp.task("default",gulp.series("one","two",function(done){
// series函數(shù)可以傳遞一系列的任務進去被順序執(zhí)行(順序苇本,不是并行的)
// 所以會出現(xiàn)先執(zhí)行前面一個再執(zhí)行后面一個,然后因為這是順序執(zhí)行的所以我們可以將default任務的處理函數(shù)放在最后
// 但是大家要明白series函數(shù)接收的是一個個任務菜拓,這就意味著一個函數(shù)也可以成為一個任務瓣窄,我們后面添加一個three試試
console.log("done")
}))
這里的報錯因為沒有調用done并且還不是異步函數(shù),所以出錯了
const gulp = require("gulp")
gulp.task("one",function(done){
console.log("one")
done()
})
gulp.task("two",function(done){
console.log("two")
done()
})
// 這里可以直接通過task方法將這個函數(shù)轉換為對應的任務
async function three(done){
console.log(three);
}
gulp.task(three);
gulp.task("default",gulp.series("one","two","three",async function(){
console.log("done")
}))
并行執(zhí)行
然后我這里寫了這些代碼
const gulp = require("gulp")
gulp.task("one",async function(){
let i = 0;
while(i<10000){
i++;
}
console.log("one執(zhí)行完成");
})
gulp.task("two",async function(){
let i = 0;
while(i<10000){
i++;
}
console.log("two執(zhí)行完成");
})
// 這里可以直接通過task方法將這個函數(shù)轉換為對應的任務
async function three(done){
let i = 0;
while(i<10000){
i++;
}
console.log("three執(zhí)行完成");
}
gulp.task(three);
// parallel函數(shù)跟series函數(shù)差不多纳鼎,只不過里面的任務會并行執(zhí)行
gulp.task("default",gulp.parallel("one","two","three",async function(){
let i = 0;
while(i<10000){
i++;
}
console.log("這是并行執(zhí)行的俺夕,我不一定是最后一個輸出了");
}))
你明白吧,我就可以直接在控制臺中查看一下情況
這真的是并行執(zhí)行的贱鄙,你沒發(fā)現(xiàn)一次性開始了所有的任務又然后中間輸出又完成所有的任務了嗎劝贸?看看series的控制臺情況吧
對比一下就知道這是并行執(zhí)行的了
嵌套
這是gulp的一個超級大亮點,就是并行和順序任務可進行過互相嵌套贰逾,并行可以嵌套在順序中悬荣,順序可以嵌套在并行中
const gulp = require("gulp")
gulp.task("one",async function(){
console.log("我第一");
})
gulp.task("two",async function(){
console.log("我第二");
})
// 這里可以直接通過task方法將這個函數(shù)轉換為對應的任務
async function three(done){
console.log("我第三");
}
gulp.task(three);
// 這就代表著會優(yōu)先并行執(zhí)行one菠秒,two等待這兩個task結束后疙剑,在順序執(zhí)行three和最后的回調函數(shù)
gulp.task("default",gulp.series(gulp.parallel("one","two"),"three",async function(){
console.log("我最后");
}))
可以互相嵌套,靈活運用哦
-
watch
自動化怎么可能少得了監(jiān)聽呢践叠?一個監(jiān)聽使用的小小例子
const gulp = require("gulp")
gulp.task("watch",async function(){
// 指定監(jiān)聽的文件
gulp.watch("js/*.js",done=>{
// 可以指定一個具體的回調函數(shù)言缤,或者指定一個或多個任務進行處理
console.log("修改了js文件");
done();
})
})
也可以使用綁定事件監(jiān)聽的方式完成文件的監(jiān)聽
const gulp = require("gulp")
const watcher = gulp.watch("js/*.js");
gulp.task("watch",async function(){
//每一個監(jiān)聽具體什么作用大家自己可以測試一下
watcher.on("change",(path,stats)=>{
console.log(path,stats);
})
watcher.on("add",(path,stats)=>{
console.log(path,stats);
})
watcher.on("unlink",(path,stats)=>{
console.log(path,stats);
})
})
常用插件
前面說了gulp的兩個插件了,分別是gulp-uglify
,gulp-babel
禁灼,這兩個插件可以說是在構建中非常常用的管挟,特別是Babel了,接下來說一說其他的插件吧
-
gulp-less
那么由于我主要用的是less作為常用css預處理器弄捕,大家可能會有用scss僻孝,stylus等等的,其實gulp也有對應的插件守谓,大家可以去npm上搜索或者百度
npm i -D gulp-less
我們首先安裝這個插件穿铆,然后我們可以在同級目錄下新建一個css文件夾在下邊創(chuàng)建一個less文件,其實gulp跟webpack還是有所不同的斋荞,因為gulp不像webpack那樣通過一個入口文件開始整合資源代碼那樣荞雏,gulp直接可以定義任務然后自動執(zhí)行就行了
@color:red;
body{
color: @color;
}
我就這樣簡單的寫一下less文件了,然后我們快速的給gulp文件定義一個處理less的任務吧
const gulp = require("gulp")
const uglify = require("gulp-uglify")
const babel = require("gulp-babel")
const less = require("gulp-less")
// 任務名就是函數(shù)的名字
gulp.task(async function minifyJS() {
// []表示匹配多個源,!就是正則表達式的非 的->意思
gulp.src(["js/*.js", "!js/*.min.js"])
.pipe(babel({
presets: ["@babel/env"]
}))
.pipe(uglify())
.pipe(gulp.dest("dist/js"))
})
gulp.task(async function tfLess() {
gulp.src("css/*.less")
.pipe(less())
.pipe(gulp.dest("dist/css"))
})
// 默認任務
gulp.task("default", gulp.parallel(
"minifyJS","tfLess"
));
然后我們這里就迅速的寫了兩個task凤优,通過default并發(fā)執(zhí)行兩個task悦陋,因為這兩個task的執(zhí)行并不會互相沖突,然后我們就可以在命令行運行
gulp
看看了
body {
color: red;
}
那么這就是我轉換之后的css文件了筑辨,你會發(fā)現(xiàn)為什么這個css文件有點不大對勁譬重,對!其實就是沒有進行壓縮啊
-
gulp-clean-css
壓縮css代碼在gulp中我們可以使用這個插件完成祷蝌,那么我看了一下這個插件的下載量還是有點客觀的婉支,就沒有使用另一款插件了(gulp-csso
)
npm install gulp-clean-css --save-dev
那么我們安裝完成這個插件之后怎么用呢,其實就是繼續(xù)在剛剛那個處理less的流基礎上再讓這個插件處理一下就行了
const gulp = require("gulp")
const uglify = require("gulp-uglify")
const babel = require("gulp-babel")
const less = require("gulp-less")
const cleanCSS = require("gulp-clean-css")
// 任務名就是函數(shù)的名字
gulp.task(async function minifyJS() {
// []表示匹配多個源痢毒,!就是正則表達式的非 的->意思
gulp.src(["js/*.js", "!js/*.min.js"])
.pipe(babel({
presets: ["@babel/env"]
}))
.pipe(uglify())
.pipe(gulp.dest("dist/js"))
})
gulp.task(async function tfLess() {
gulp.src("css/*.less")
.pipe(less())
.pipe(cleanCSS({compatibility: 'ie8'}))
.pipe(gulp.dest("dist/css"))
})
// 默認任務
gulp.task("default", gulp.parallel(
"minifyJS","tfLess"
));
那么這下打包之后大家再看一下自己的css文件就發(fā)現(xiàn)已經(jīng)完全的minify了送矩,那么關于這個插件,介紹是說這個插件是clean-css
在gulp上的實現(xiàn)哪替,其實就是包裝了一下clean-css
栋荸,所以這個插件可以使用clean-css
的API,那么上面用到的compatibility
(兼容性)選項就是clean-css
的凭舶,關于clean-css
的更多信息傳送
(周下載超500w次晌块,你明白吧)
那么介紹一些其他的插件吧
-
gulp-concat
顧名思義就是用來連接多個文件的
這里我們可以在js文件夾中新建一個02.js
文件
for(let i=0;i<1000;i++){
console.log(i);
}
let j = 0;
while(j<10000){
j++;
}
console.log("done");
為了節(jié)省時間就隨便寫了幾行代碼,然后我們快速安裝使用下吧
npm install --save-dev gulp-concat
const gulp = require("gulp")
const uglify = require("gulp-uglify")
const babel = require("gulp-babel")
const less = require("gulp-less")
const cleanCSS = require("gulp-clean-css")
const concat = require("gulp-concat")
// 任務名就是函數(shù)的名字
gulp.task(async function minifyJS() {
// []表示匹配多個源帅霜,!就是正則表達式的非 的->意思
gulp.src(["js/*.js", "!js/*.min.js"])
.pipe(babel({
presets: ["@babel/env"]
}))
// 在壓縮之前合并js文件
// 需要換入合并之后的文件名
.pipe(concat("all.js"))
.pipe(uglify())
.pipe(gulp.dest("dist/js"))
})
gulp.task(async function tfLess() {
gulp.src("css/*.less")
.pipe(less())
.pipe(cleanCSS({compatibility: 'ie8'}))
.pipe(gulp.dest("dist/css"))
})
// 默認任務
gulp.task("default", gulp.parallel(
"minifyJS","tfLess"
));
你就會發(fā)現(xiàn)合并竟然是如此的簡單匆背,你以為這樣就結束了,不你錯了身冀,它不僅可以合并js文件同樣也可以合并css文件钝尸,你明白吧,只需要修改對應的css文件處理任務函數(shù)
gulp.task(async function tfLess() {
gulp.src("css/*.less")
.pipe(less())
.pipe(concat("index.css"))
.pipe(cleanCSS({compatibility: 'ie8'}))
.pipe(gulp.dest("dist/css"))
})
-
gulp-rename
這個東西顧名思義搂根,我們肯定需要將打包后的js或者css文件改成min格式的吧珍促,所以就需要使用這個工具了
npm i -D gulp-rename
const gulp = require("gulp")
const uglify = require("gulp-uglify")
const babel = require("gulp-babel")
const less = require("gulp-less")
const cleanCSS = require("gulp-clean-css")
const concat = require("gulp-concat")
const rename = require("gulp-rename")
// 任務名就是函數(shù)的名字
gulp.task(async function minifyJS() {
// []表示匹配多個源,!就是正則表達式的非 的->意思
gulp.src(["js/*.js", "!js/*.min.js"])
.pipe(babel({
presets: ["@babel/env"]
}))
// 在壓縮之前合并js文件
// 需要換入合并之后的文件名
.pipe(concat("all.js"))
.pipe(uglify())
.pipe(rename(path => {
// 這里我們只需要修改basename屬性即可
// 若需要查看有哪些可修改屬性請
// console.log(path)
path.basename += "-min";
}))
.pipe(gulp.dest("dist/js"))
})
gulp.task(async function tfLess() {
gulp.src("css/*.less")
.pipe(less())
.pipe(concat("index.css"))
.pipe(cleanCSS({ compatibility: 'ie8' }))
.pipe(rename(path => {
// 這里我們只需要修改basename屬性即可
// 若需要查看有哪些可修改屬性請
// console.log(path)
path.basename += "-min";
}))
.pipe(gulp.dest("dist/css"))
})
// 默認任務
gulp.task("default", gulp.parallel(
"minifyJS", "tfLess"
));
rename差不多到這就行了剩愧,我們重命名一般都是+個.min之類的猪叙,所以夠用了
-
del
你會發(fā)現(xiàn)如果在你沒有刪文件的前提下,你的dist文件夾下的文件應該可以說是非常的多了吧仁卷,絕對不是一個文件夾對一個一個文件了吧穴翩,那么這是樓主的目錄結構
你就會發(fā)現(xiàn)每一次的構建都會生成一個新的文件,如果文件名以替換又會生成一個新的文件锦积,這樣的話我們dist目錄下可能就會出現(xiàn)很多無用的文件了芒帕,這時候我們就需要使用這個插件了
npm install --save-dev del
然后我們可能需要稍微改動一下默認task,這里建議大家使用series函數(shù)包裹,因為這樣可以指定最后一個函數(shù)為default的處理函數(shù)充包,用parallel就不行
const gulp = require("gulp")
const uglify = require("gulp-uglify")
const babel = require("gulp-babel")
const less = require("gulp-less")
const cleanCSS = require("gulp-clean-css")
const concat = require("gulp-concat")
const rename = require("gulp-rename")
const del = require("del")
// 任務名就是函數(shù)的名字
gulp.task(async function minifyJS() {
// []表示匹配多個源副签,!就是正則表達式的非 的->意思
gulp.src(["js/*.js", "!js/*.min.js"])
.pipe(babel({
presets: ["@babel/env"]
}))
// 在壓縮之前合并js文件
// 需要換入合并之后的文件名
.pipe(concat("all.js"))
.pipe(uglify())
.pipe(rename(path => {
// 這里我們只需要修改basename屬性即可
// 若需要查看有哪些可修改屬性請
// console.log(path)
path.basename += "-min";
}))
.pipe(gulp.dest("dist/js"))
})
gulp.task(async function tfLess() {
gulp.src("css/*.less")
.pipe(less())
.pipe(concat("index.css"))
.pipe(cleanCSS({ compatibility: 'ie8' }))
.pipe(rename(path => {
// 這里我們只需要修改basename屬性即可
// 若需要查看有哪些可修改屬性請
// console.log(path)
path.basename += "-min";
}))
.pipe(gulp.dest("dist/css"))
})
gulp.task(async function cleanDir(){
// 刪除dist目錄下所有文件/目錄
// 也可以傳入一個數(shù)組刪除多個文件或者目錄等等
return del("dist/**/*")
})
// 默認任務
gulp.task("default", gulp.series(
"cleanDir",
gulp.parallel("minifyJS", "tfLess")
));
這樣我們就實現(xiàn)了一個使用先刪除輸出文件夾下所有文件然后再輸出的功能
-
gulp-markdown
這個插件怎么說呢遥椿?對于我們而言還是有點作用的,這個插件可以將md文件語法轉換成html輸出
npm install --save-dev gulp-markdown
const gulp = require("gulp")
const uglify = require("gulp-uglify")
const babel = require("gulp-babel")
const less = require("gulp-less")
const cleanCSS = require("gulp-clean-css")
const concat = require("gulp-concat")
const rename = require("gulp-rename")
const del = require("del")
const markdown = require("gulp-markdown")
// 任務名就是函數(shù)的名字
gulp.task(async function minifyJS() {
// []表示匹配多個源淆储,!就是正則表達式的非 的->意思
gulp.src(["js/*.js", "!js/*.min.js"])
.pipe(babel({
presets: ["@babel/env"]
}))
// 在壓縮之前合并js文件
// 需要換入合并之后的文件名
.pipe(concat("all.js"))
.pipe(uglify())
.pipe(rename(path => {
// 這里我們只需要修改basename屬性即可
// 若需要查看有哪些可修改屬性請
// console.log(path)
path.basename += "-min";
}))
.pipe(gulp.dest("dist/js"))
})
gulp.task(async function tfLess() {
gulp.src("css/*.less")
.pipe(less())
.pipe(concat("index.css"))
.pipe(cleanCSS({ compatibility: 'ie8' }))
.pipe(rename(path => {
// 這里我們只需要修改basename屬性即可
// 若需要查看有哪些可修改屬性請
// console.log(path)
path.basename += "-min";
}))
.pipe(gulp.dest("dist/css"))
})
gulp.task(async function cleanDir(){
// 刪除dist目錄下所有文件/目錄
// 也可以傳入一個數(shù)組刪除多個文件或者目錄等等
return del("dist/**/*")
})
gulp.task(async function tfMD(){
gulp.src("md/01.md")
.pipe(markdown())
.pipe(gulp.dest("dist/md"))
})
// 默認任務
gulp.task("default", gulp.series(
"cleanDir",
gulp.parallel("minifyJS", "tfLess")
));
-
gulp-imagemin
壓縮 PNG, JPEG, GIF 和 SVG 圖片的一個插件
npm install --save-dev gulp-imagemin
(使用起來都是一樣的)
-
gulp.spritesmith
這東西對于前端的性能優(yōu)化來說還是挺有用的冠场,可以將多張圖片合并為一張精靈圖,這樣可以減少很多http請求本砰,明白吧碴裙!
(這兩個插件后續(xù)更新,因為目前沒有合適的圖片使用)
(其實gulp有許多的有意思的小插件点额,大家可以去gulp的插件市場瀏覽一下)
分享一些使用gulp中遇到的問題
- 最新的gulp4,在進行使用
gulp.series
進行順序task或者異步taskgulp.parallel
的時候會出現(xiàn)一些,就是你會發(fā)現(xiàn)使用了async函數(shù),會出現(xiàn)順序無法按照預期的順序執(zhí)行task,但是如果使用done回調函數(shù)的話,因為stream是異步的而且gulp.dest
沒有提供回調,io操作不知道什么時候完成也解決不了這個問題,這就陷入了一個死節(jié)了,不知道應該怎么辦?后面我是怎么做的呢,好像gulp官方要求series或者parallel返回一個stream,所以說后面我按照這個要求去掉了async去掉了done回調,直接返回一個gulp.src解決問題了,可以給大家看一下最近我寫的一個gulpfile.js
const gulp = require("gulp");
const cssClean = require('gulp-clean-css');
const rename = require("gulp-rename");
const uglify = require("gulp-uglify");
// 兩個插件用于修改html文件中的引用資源路徑
const rev = require('gulp-rev');
// 通過此插件改寫html引用的路徑
const revReplace = require('gulp-rev-replace');
const htmlmin = require('gulp-htmlmin');
const del = require("del");
gulp.task("cleanDir", () => del("qian/**"))
// minify css
gulp.task('cssMin', () => {
return gulp.src("qian/css/*.css")
.pipe(cssClean({ compatibility: 'ie9' }))
.pipe(gulp.dest('qian/css'));
});
// uglify js --> 同時壓縮了代碼,混肴了代碼
gulp.task(function jsMin() {
return gulp.src("qian/js/*.js")
.pipe(uglify())
.pipe(gulp.dest("qian/js"));
})
// 首先生成對應的manife.json文件然后進行優(yōu)化對應文件,最后替換路徑
gulp.task(function genManifest() {
return gulp.src(["dist/css/*.css", "dist/js/*.js"], { base: "dist" })
// .pipe(gulp.dest('qian'))
.pipe(rev())
.pipe(rename(path => {
// console.log(path);
path.basename += ".min";
}))
.pipe(gulp.dest('qian'))
.pipe(rev.manifest())
.pipe(gulp.dest('qian/rev'))
})
gulp.task(function Done() {
return gulp.src("dist/index.html")
.pipe(revReplace({ manifest: gulp.src("qian/rev/*.json") }))
.pipe(htmlmin({
minifyJS: true,
minifyCSS: true,
removeComments: true, //清除HTML注釋
collapseWhitespace: true, //壓縮HTML
}))
.pipe(gulp.dest("qian"))
})
gulp.task("default", gulp.series(
"cleanDir",
gulp.parallel("cssMin", "jsMin"),
"genManifest",
"Done",
function myHook(){
return gulp.src("dist/favicon.ico").pipe(gulp.dest("qian"));
}
));
- 關于上面的寫這個
gulpfile.js
的時候又遇到了新的問題,因為使用了webpack打包這些東西,使用gulp構建的時候出現(xiàn)了一些問題,就是比如說我們需要去壓縮css或者混肴壓縮js或者壓縮html等等那么我們需要標準化文件的名稱為+-min
,因為是自動化的工具,所以我們需要自動化啊,但是如果我們更改了這些資源的名稱,那么我們就需要手動的去修高html文件中的資源引用路徑,這就不符合自動化的觀念了,所以后面通過搜集資料開始了解到了兩個插件
gulp-rev
gulp-rev-collector
那么根據(jù)一些資料,大概就是通過gulp-rev
生成修改之前的文件資源的路徑與生成之后的文件資源路徑的對應關系為一個json文件,然后gulp-rev-collector
插件通過解析這個json文件,進行正則匹配html文件中對應的資源進行替換資源
-
那么這是我html文件中的引用關系
-
通過gulp生成的對應關系
那么這里主要是想跟大家分享一些解決這些問題的經(jīng)驗,避免少走彎路,那么之后出現(xiàn)了一個什么問題了,發(fā)現(xiàn)生成之后的html文件根本就沒有替換靜態(tài)引用資源路徑,真的,為了解決這個問題花了3個小時的時間,當時解決的差點懷疑人生了,最后我拋開了自己的問題,覺得肯定是這個插件的問題!
所以我又遇見了另一個插件
gulp-rev-replace
真的,解決這個問題差點搞得我崩潰,那么替換為上面這個插件之后,問題基本上就已經(jīng)完美解決了,白花花花了3個小時的時間,希望大家千萬不要踩坑用哪個坑爹的gulp-rev-collector
,當然也有可能是因為樓主用的姿勢不對,但是不管怎么說如果你用這個插件如果不行,千萬不要考慮解決,直接換上面這個replace
插件吧
還有就是如果需要動態(tài)的替換這些引用資源的路徑,必須要保證在rev生成的manife.json文件之后不要修改 文件名
切記
問題分享就到這了
教程遠沒有結束舔株,如果還有可以分享的插件,我也會一直更新下去还棱,記得查看最后時間哦
有沒有啥相對我說的或者交流的或者你對學習前端有困惑什么的载慈,可以聯(lián)系我哈群
78484-->5854
,偷偷告訴你樓主是自學的珍手,并且不會英語哦