<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          對比webpack,你更應(yīng)該先掌握gulp【10分鐘教你徹底掌握gulp】

          共 6496字,需瀏覽 13分鐘

           ·

          2021-01-19 23:12


          前言

          可能很多人對于gulp都相對陌生,特別是vuereact出現(xiàn)以后,漸漸淡出了做業(yè)務(wù)前端人員的視野,14到16年的時候應(yīng)該是它最巔峰的時候,真正的是出道即巔峰,取代了當時最火的grunt成為了前端構(gòu)建的主流工具,就連某度都忍不住來瓜分一下流量,出了個fis(不過按照爛尾的慣例來看,基本會屬于后繼無人的狀態(tài),所以沒有真正去用在生產(chǎn)項目中過),而且當時webpack雖然已經(jīng)出現(xiàn),但完全不能跟gulp抗衡,直到vuereactspa項目出現(xiàn),才讓webpack取而代之,gulp也逐漸退出幕前,轉(zhuǎn)戰(zhàn)幕后,去做了它更擅長的事情:前端開發(fā)流程規(guī)范管理

          現(xiàn)在我們在各種組件庫,像antdelement-uivant等比較人們的組件庫,或者其他一些前端工程中都能看到它的身影,只不過它不再介入到業(yè)務(wù)的實際生產(chǎn)開發(fā)中了,所以對業(yè)務(wù)開發(fā)人員來說是不太能感知到它的存在了。

          gulp和webpack的區(qū)別

          首先,可能很多人面試過程中都會被問到這個問題。我說一說自己的理解:

          gulpwebpack
          強調(diào)的是規(guī)范前端開發(fā)的流程是一個前端模塊化方案
          是一個基于流的自動化構(gòu)建工具,不包括模塊化的功能,通過配置一系列的task,例如文件壓縮合并、雪碧圖、啟動server、版本控制等,然后定義執(zhí)行順序來讓gulp執(zhí)行task,從而構(gòu)建前端項目的流程是一個自動化模塊打包工具,把開發(fā)中的所有資源(圖片、js文件、css文件等)都看成模塊,通過loader(加載器)和plugins(插件)對資源進行處理,劃分成不同的模塊,需要哪個加載哪個,實現(xiàn)按需加載的功能,入口引入的更多是js文件

          webpack剛面世的時候,webpackgulp中也有一個插件(gulp-webpack)作為使其可以作為gulp?一個子任務(wù)來執(zhí)行。只不過當時還是JQuery的時代,功能基本重復(fù),真正使用webpack的還是很少,所以reactspa框架的出現(xiàn)讓webpack迅速躥紅。

          gulp的核心api

          task, series, parallel, src, pipe, dest, on, watch

          • task: 創(chuàng)建一個任務(wù)
          • series:順序執(zhí)行多個任務(wù)
          • prallel:并行執(zhí)行多個任務(wù)
          • src:讀取數(shù)據(jù)源轉(zhuǎn)換成stream
          • pipe:管道-可以在中間對數(shù)據(jù)流進行處理
          • dest:輸出數(shù)據(jù)流到目標路徑
          • on:事件監(jiān)聽
          • watch:數(shù)據(jù)源監(jiān)聽

          這些api在demo中都有用一個例子串起來講解使用

          其他的基本很少會用到了,這里就不多復(fù)述,網(wǎng)上的很多文章,還有官方的api都有詳細的,但在實際的開發(fā)中我基本很少用到,可能是使用的場景過于簡單吧

          本文就用一個實際的例子把這幾個api全部串聯(lián)起來,我將實現(xiàn)一個這樣的功能:

          流程管理

          全局安裝gulp

          $?npm?i?gulp?-g

          項目根目錄新建gulpfile.js文件

          文件頭引入模塊

          //?gulpfile.js
          const?gulp?=?require("gulp");
          /**
          ?*?合并文件插件
          ?*?gulp的插件很多,有4000多個,足夠滿足大家日常的各種需求,而且插件寫起來也超級簡單
          ?*/

          const?concat?=?require("gulp-concat");
          const?through2?=?require("through2");

          創(chuàng)建合并文件任務(wù)

          新建合并任務(wù),讀取20201108目錄下所有txt文件,合并為20201108.txt文件并存儲在demo文件夾下

          //?task?為創(chuàng)建gulp子任務(wù)
          gulp.task('concat',?()?=>?{
          ??return?gulp.src('./20201108/*.txt')?//?src:?讀取文件轉(zhuǎn)化為可讀流,參數(shù)可以是文件通配符匹配
          ???????.pipe(gulpConcat('20201108.txt'))?//?pipe:管道,把gulp的執(zhí)行步驟一步步串聯(lián)起來,也是gulp的核心
          ???????.pipe(dest('./demo/'))?// dest:存放文件
          ????.on('end',?()?=>?{?//?事件監(jiān)聽
          ????console.log('concat:?文件合并完成');
          ????})
          })

          創(chuàng)建文件去除空行任務(wù)

          因為是需要順序執(zhí)行子任務(wù),所以用的series,如果是需要并行執(zhí)行的話用parallel

          代碼中的through2主要是用來做文件流轉(zhuǎn)換過濾,寫gulp插件必備,下一節(jié)會大概的介紹一下

          gulp.task('format',?gulp.series('concat',?()?=>?{
          ??return?gulp.src('./demo/20201108.txt')
          ????.pipe(through2.obj(function?(file,?encoding,?cb)?{?// through2:文件流轉(zhuǎn)換,寫gulp插件必備,下面會大概的介紹一下
          ????let?contents?=?file.contents.toString();
          ????contents?=?contents
          ?????.replace(/(\n[\s\t]*\r*\n)/g,?"\n")
          ?????.replace(/^[\n\r\n\t]*|[\n\r\n\t]*$/g,?"");?//?去除空行
          ????let?lines?=?contents.split(/\n/g);
          ????totalLine?=?lines.length;
          ????contents?=?lines.join("\n");
          ????file.contents?=?Buffer.from(contents);
          ????this.push(file);
          ????cb();
          ???}))
          ???.pipe(dest('./demo/'))
          ???.on('end',?()?=>?{
          ????console.log('format:?去除空行完成');
          ???})
          }))

          創(chuàng)建監(jiān)聽任務(wù)

          20201108文件夾下的文件有寫入操作時,去執(zhí)行format任務(wù),format任務(wù)又依賴concat任務(wù)執(zhí)行

          gulp.task('watch',?()?=>?{
          ??//?因為是需要順序執(zhí)行子任務(wù),所以用的concat,如果是需要并行執(zhí)行的話用parallel
          ??gulp.watch('./20201108/*.txt',?gulp.series('format',?(cb)?=>?{
          ??cb();
          ??})).on('change',?()?=>?{?//?更多事件監(jiān)聽可以查看官方文檔
          ??console.log('watch:?文件被改變');
          ?})
          })

          在項目目錄下執(zhí)行

          以上幾步的代碼合并到一個gulpfile.js文件中即可運行

          #?監(jiān)控20201108文件夾下所有文件變化,則執(zhí)行format子任務(wù)
          $?gulp?watch

          下圖為命令行中輸入日志

          圖片

          看了上面的demo可能大家會對through2比較好奇吧,接下來會大概介紹一下

          gulp插件機制

          我們先提一提gulp的機制,gulp內(nèi)部的實現(xiàn)很簡單,用了三個sdk實現(xiàn)undertakervinyl-fs, glob-watcher

          • undertaker: 主要用來實現(xiàn)gulp的子任務(wù)流程管理

          • vinyl-fs: .src 接口可以匹配一個文件通配符,將匹配到的文件轉(zhuǎn)為Vinyl Stream(流),gulp理念就是萬物皆可流

          • glob-watcher: 也就是去實現(xiàn)gulp.watch功能,監(jiān)控文件流變化

          核心就是把文件轉(zhuǎn)換成Stream流,然后對Stream進行操作。

          所以gulp采用pipe(管道)的概念,意味著順著管道流淌,然后我們對于gulp的插件,也很好理解了,就是在管道中間有個過濾站,對流進行過濾處理,這就用到了上面提到的through2,這個插件主要的作用也是對流文件進行處理,類似的插件還有map-stream等,不過gulp的主流的插件都是基于through2編寫的.

          例如上面的例子(文件去除空行任務(wù)),單獨封裝一下,使用的時候就是一個簡單的插件

          //?gulp-file-format.js

          module.exports?=?()?=>?{
          ??return?through2.obj(function?(file,?encoding,?cb)?{
          ?let?contents?=?file.contents.toString();
          ?contents?=?contents
          ??.replace(/(\n[\s\t]*\r*\n)/g,?"\n")
          ??.replace(/^[\n\r\n\t]*|[\n\r\n\t]*$/g,?"");?//?去除空行
          ?let?lines?=?contents.split(/\n/g);
          ?totalLine?=?lines.length;
          ?contents?=?lines.join("\n");
          ?file.contents?=?Buffer.from(contents);
          ?this.push(file);
          ?cb();
          ??})
          }

          替換文件去除空行任務(wù)

          const?gulpFormact?=?require('gulp-file-format.js');

          gulp.task('format',?gulp.series('concat',?()?=>?{
          ??return?gulp.src('./demo/20201108.txt')
          ????.pipe(gulpFormact())
          ????.pipe(dest('./demo/'))
          ????.on('end',?()?=>?{
          ????console.log('format:?去除空行完成');
          ????})
          }))

          這就是一個很簡單的gulp插件了,是不是很簡單,比webpack的插件簡單多了

          下面講一個日常中對于重復(fù)工作提效寫的一個腳本,講講思路,讓大家對gulp的使用場景有個更深的理解。

          實際應(yīng)用案例思路拆解-支付中間頁改版后數(shù)據(jù)統(tǒng)計

          由于實際的代碼涉及到一些敏感數(shù)據(jù),所以這個段落只是講一下解決這個實際問題的思路拆解,怎么去用gulp完成想要的結(jié)果,不貼詳細的代碼了。

          例如,作者最近做了一個支付中間頁的改版

          我需要統(tǒng)計從這個支付中間頁轉(zhuǎn)化的用戶產(chǎn)生了多少收入,人工流程如下:

          統(tǒng)計流程

          把以上幾個步驟拆解成gulp的任務(wù),用gulp的任務(wù)機制管理起來,每一個任務(wù)可以單獨執(zhí)行,又可以統(tǒng)一執(zhí)行

          1. export:下載用戶uid
          //?導(dǎo)出uid表
          gulp.task('export',?()?=>?{})
          1. concat:合并文件并去重
          //?對excel文件進行合并去重
          gulp.task('cocat',?()?=>?{})
          1. money:循環(huán)uid,遠程請求接口,拿到支付金額
          //?獲取每一個uid的支付金額
          gulp.task('money',?()?=>?{})
          1. total: 匯總數(shù)據(jù),生成匯總excel表格并輸出
          //?數(shù)據(jù)匯總
          gulp.task('total',?gulp.series('export',?'concat',?'money',?(cb)?=>?{
          ?//...
          }))
          1. 執(zhí)行命令
          $?gulp?total

          以上任務(wù)都可以獨立執(zhí)行,也可以合并執(zhí)行

          更復(fù)雜的應(yīng)用場景-轉(zhuǎn)轉(zhuǎn)sdk生成命令工具

          更復(fù)雜的應(yīng)用場景可以查看我們之前產(chǎn)出的一套sdk命令生成工具:commander-tools,現(xiàn)已在github開源,在轉(zhuǎn)轉(zhuǎn)支撐團隊的維護下功能越來強大,主要實現(xiàn)以下命令:

          {
          ??"scripts":?{
          ????"lint":?"commander-tools?run?lint",?//?校驗
          ????"fix":?"commander-tools?run?lint?--fix",?//?修復(fù)
          ????"staged":?"commander-tools?run?lint?--staged",
          ????"staged-fix":?"commander-tools?run?lint?--staged?--fix",
          ????"dev":?"commander-tools?run?dev",?//?啟動本地調(diào)試服務(wù)
          ????"compile":?"commander-tools?run?compile",?//?編譯
          ????"dist":?"commander-tools?run?dist",?//?外鏈打包
          ????"analyz":?"commander-tools?run?dist?--analyz",?//?代碼分析
          ????"build":?"commander-tools?run?build",
          ????"pub":?"commander-tools?run?pub",?//?發(fā)布正式版
          ????"pub-beta":?"commander-tools?run?pub-beta",?//?發(fā)布beta版本
          ????"unpub":?"commander-tools?run?unpub",?//?卸載版本
          ????"doc":?"commander-tools?run?doc",?//?預(yù)覽文檔
          ????"build-doc":?"commander-tools?run?build-doc",?//?生成文檔
          ????"doc-upload":?"commander-tools?run?doc-upload"?//?文檔上傳ftp
          ??}
          }

          例如:一個上傳注釋文檔的功能

          $?npm?run?doc-upload
          /**
          *?上傳文檔
          **/

          const?chalk?=?require('chalk')
          const?ftp?=?require('vinyl-ftp')
          gulp.task('doc-upload',?gulp.series('build-doc',?done?=>?{
          console.log(chalk.green('running?doc-upload'))

          if?(!ftpConfig)?{
          ??console.log(chalk.red('請配置?ftp.config.js'))
          ??process.exit(1)
          }?else?{
          ??const?businessLine?=?getBusinessLine(program)
          ??const?{?name?}?=?packageJson
          ??const?conn?=?ftp.create({
          ????parallel:?10,
          ????log:?fancyLog,
          ????...ftpConfig
          ??})

          ??const?pipe?=?gulp
          ????.src(`${cwd}/${program.docsDirName?||?'docs'}/**/*`)
          ????.pipe(conn.dest(`/${businessLine}/${name}/`))
          ????.on('end',?()?=>?{
          ??????console.log(chalk.green('Success:?文檔上傳成功'))
          ??????ftp.docUrl?&&?open(ftp.docUrl)
          ????})

          ??return?pipe
          }
          }))

          以上命令保證轉(zhuǎn)轉(zhuǎn)的所有sdk都能實現(xiàn)按需加載,并且規(guī)范化輸出

          結(jié)語

          如果只是想用一個很簡單的小功能,不用寫繁瑣的node腳本,不用去配置復(fù)雜的webpackgulp不超過10行代碼就能幫你搞定,它豐富的插件生態(tài)基本能滿足你所有的功能需求,簡直就是提升開發(fā)效率的利器。

          參考資料

          • gulp官網(wǎng)
          • gulp插件集合
          • commander-tools
          • 文件通配符

          瀏覽 75
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  乱伦一级视频 | 日本一道本高清在线一区二区 | 亚洲国产精品毛片一区二区三区 | 成人黄色在线电影 | 亚洲欧美毛片高清 |