前端工程師:我用gup4.0搭建一個前端腳手架

2020-12-21 酷扯兒

本文轉載自【微信公眾號:趣談前端,ID:beautifulFront】經微信公眾號授權轉載,如需轉載與原文作者聯繫

本文將會介紹如何使用gulp4來搭建項目腳手架,如果您還在使用gulp3或更老的版本,您也以通過本文的一些思想將之前的項目進行完善,更新。如果gulp不是你們團隊的重點,也可以移步我的Webpack4.0搭建文章.

前言

由於本文重點是介紹gulp4.0搭建腳手架的思路,相關插件的用法以及項目結構的設計,由於gulp的基本用法很簡單,如果不熟悉可以移步官網自行研究學習。該腳手架的設計思路和功能如下:

同時為了提高開發環境的效率,這裡我們參考webpack的配置,區分開發環境和生產環境,在接下來將會具體介紹。

腳手架用到的第三方插件介紹

gulp-jshint ——js語法檢測gulp-util ——終端控制臺列印自定義錯誤信息http-proxy-middleware ——設置代理,配合gulp-connect使用gulp-less ——將less編譯成cssgulp-file-include ——用於文件模塊化導入,如用include的方式導入公共部分gulp-connect ——用於啟動本地伺服器gulp-clean ——清理目錄gulp-uglify --壓縮jsgulp-minify-css ——壓縮cssgulp-autoprefixer ——自動添加瀏覽器前綴imagemin-pngquant ——png圖片壓縮gulp-imagemin ——圖壓縮gulp-cache ——設置gulp打包的緩存,一般用於imggulp-md5-plus ——將文件名進行md5處理便於打包更新當然gulp還有很多常用的插件可以更好的為我們的項目服務,大家也可以整合自己的插件讓項目更加完善。

項目目錄設計

1.src目錄,即我們開發項目時的源目錄,具體結構如下:

我們定義views是我們視圖層,即頁面文件的目錄,js目錄為業務邏輯的腳本文件,lib存放第三方框架,include目錄為公共部分的存放目錄,我們可以用gulp-file-include來導入到html中,images和css大家都比較清楚,分別時存放image和css文件的目錄。

2. dist目錄,即輸出的目錄,具體結構如下:

可以看到我們會看到src打包後的目錄對應static目錄,為什麼我們會加一層static呢?我的設計是如果項目使用node等服務層框架,我們可以用gulp一併打包放入dist下,這樣dist就是一個完整的包括前後端服務的項目目錄了,當然大家也可以直接將src打包後的文件和文件夾直接放到dist下,根具業務需求靈活設計吧。

在這裡我要說一點,由於筆者親測gulp-md5-plus有時候打包不穩定,可能不會給html自動添加對應的md5後綴,所以筆者在這塊做了特殊的處理,如果大家在工作中有更好的方案,可以及時和筆者溝通交流。

3. gulpfile文件配置

由於我們要區分開發環境和生產環境,所以這裡我們使用兩個不同的配置文件,根據NODE_ENV來區分用哪個文件。

我們將配置文件統一放到build目錄下,config為公共配置文件,gulp.dev.js和gulp.prod.js分別為開發和生產環境配置文件。我們整體的目錄結構如下:

腳手架完整源碼(部分插件和配置會給出詳細注釋)

config.js

module.exports = {dist: './dist/static', // 配置構建目錄}

gulp.dev.js

const gulp = require('gulp');// jsconst Jshint = require("gulp-jshint"); //js檢查const Gutil = require('gulp-util');const Proxy = require('http-proxy-middleware');// const Webpack = require('webpack');// const WebpackConfig = require('./webpack.config.js');// cssconst Less = require('gulp-less'); // 編譯less// htmlconst FileInclude = require('gulp-file-include'); // 文件模塊化// serverconst Connect = require('gulp-connect'); //引入gulp-connect模塊 const Clean = require('gulp-clean'); // 清理目錄// 配置文件const config = require('./config');const { dist } = config;// htmlasync function html() {return gulp.src('src/views/*.html') .pipe(FileInclude({ // HTML模板替換,具體用法見下文 prefix: '##', basepath: '@file' })).on('error', function(err) { console.error('Task:copy-html,', err.message); this.end(); }) .pipe(gulp.dest(dist)) // 拷貝 .pipe(Connect.reload())}// cssasync function css() { return await gulp.src('src/css/*.less') .pipe(Less()) //編譯less .pipe(gulp.dest(dist + '/css')) //當前對應css文件 .pipe(Connect.reload());//更新}// js// const compilerJS = Webpack(WebpackConfig);async function js() { return await gulp.src('src/js/**') .pipe(Jshint())//檢查代碼 // .pipe(Babel({ // presets: ['es2015'] // })) .on('error', function(err) { Gutil.log(Gutil.colors.red('[Error]'), err.toString()); }) .pipe(gulp.dest(dist + '/js')) // 拷貝 .pipe(Connect.reload()); //更新 // 使用es6+可以單獨配置 // compilerJS.run(function(err, stats) { // if(err) throw new Gutil.PluginError("webpack:js", err); // Gutil.log("[webpack]", stats.toString({ // colors: true // })); // cb() // });}// imageasync function image() { return await gulp.src('src/images/*') .pipe(gulp.dest(dist + '/images'));}// clean dirasync function clean() { // 不設置allowEmpty: true會報File not found with singular glob return await gulp.src(dist, {allowEmpty: true}).pipe(Clean());}// 伺服器函數async function server() { Connect.server({ root:dist, //根目錄 // ip:'192.168.11.62',//默認localhost:8080 livereload:true, //自動更新 port:9909, //埠 middleware: function(connect, opt) { return [ Proxy('/api', { target: 'http://localhost:8080', changeOrigin:true }), Proxy('/otherServer', { target: 'http://IP:Port', changeOrigin:true }) ] } })}module.exports = { html, css, js, image, clean, server}

gulp.prod.js

const gulp = require('gulp');// const Rename = require('gulp-rename'); // 重命名// jsconst Uglify = require('gulp-uglify'); // 壓縮js// const Babel = require('gulp-babel');// cssconst Minifycss = require('gulp-minify-css'); // 壓縮cssconst Less = require('gulp-less'); // 編譯lessconst Autoprefixer = require('gulp-autoprefixer'); // 瀏覽器前綴// htmlconst MinifyHtml = require("gulp-minify-html"); //壓縮htmlconst FileInclude = require('gulp-file-include'); // 文件模塊化// imageconst Imagemin = require('gulp-imagemin');const Pngquant = require('imagemin-pngquant'); //png圖片壓縮插件const Cache = require('gulp-cache'); const Clean = require('gulp-clean'); // 清理目錄// md5 發版本的時候為了避免瀏覽器讀取了舊的緩存文件,需要為其添加md5戳const md5 = require("gulp-md5-plus");const config = require('./config');const { dist } = config;// htmlasync function html() {return gulp.src('src/views/*.html') .pipe(FileInclude({ // HTML模板替換,具體用法見下文 prefix: '##', basepath: '@file' })) // .pipe(MinifyHtml()) .on('error', function(err) { console.error('Task:copy-html,', err.message); this.end(); }) .pipe(gulp.dest(dist)) // 拷貝 }// cssasync function css() { return await gulp.src('src/css/**') .pipe(Less()) //編譯less .pipe(Autoprefixer({ cascade: true, //是否美化屬性值 默認:true 像這樣: //-webkit-transform: rotate(45deg); // transform: rotate(45deg); remove: true //是否去掉不必要的前綴 默認:true })) .pipe(Minifycss({ // 壓縮css //類型:Boolean 默認:true [是否開啟高級優化(合併選擇器等)] advanced: true, //保留ie7及以下兼容寫法 類型:String 默認:''or'*' [啟用兼容模式; 'ie7':IE7兼容模式,'ie8':IE8兼容模式,'*':IE9+兼容模式] compatibility: '', //類型:Boolean 默認:false [是否保留換行] keepBreaks: false, //保留所有特殊前綴 當你用autoprefixer生成的瀏覽器前綴,如果不加這個參數,有可能將會刪除你的部分前綴 keepSpecialComments: '*' })) .pipe(gulp.dest(dist + '/css')) .pipe(md5(10, dist + '/*.html', { mappingFile: 'manifest.json', connector: '.' // 文件名和hash的連接符 })) .pipe(gulp.dest(dist + '/css')) //當前對應css文件}// jsasync function js() { return await gulp.src('src/js/**') // .pipe(Babel({ // presets: ['es2015'] // })) .pipe(Uglify()) // 壓縮js .pipe(gulp.dest(dist + '/js')) .pipe(md5(10, dist + '/*.html', { mappingFile: 'manifest.json', connector: '.' })) .pipe(gulp.dest(dist + '/js')) // 拷貝}// imageasync function image() { return await gulp.src('src/images/*') .pipe(Cache(Imagemin({ optimizationLevel: 5, //類型:Number 默認:3 取值範圍:0-7(優化等級) progressive: true, //類型:Boolean 默認:false 無損壓縮jpg圖片 interlaced: true, //類型:Boolean 默認:false 隔行掃描gif進行渲染 multipass: true, //類型:Boolean 默認:false 多次優化svg直到完全優化 svgoPlugins: [{removeViewBox: false}],//不要移除svg的viewbox屬性 use: [Pngquant()] //使用pngquant深度壓縮png圖片的imagemin插件 }))) .pipe(gulp.dest(dist + '/images'));}// clean dirasync function clean() { // 不設置allowEmpty: true會報File not found with singular glob return await gulp.src(dist, {allowEmpty: true}).pipe(Clean());}module.exports = { html, css, js, image, clean}

gulpfile.js

const gulp = require('gulp');// 根據環境引入不同的配置文件let buildConfig;if(process.env.NODE_ENV === 'dev') {buildConfig = require('./build/gulp.dev'); gulp.task('server', buildConfig.server); // 本地服務} else { buildConfig = require('./build/gulp.prod'); // gulp.task('md5', gulp.series(buildConfig.md5Css, buildConfig.md5Js)); gulp.task('clean', buildConfig.clean); // 清理目錄 }gulp.task('html', buildConfig.html); // 打包htmlgulp.task('js', buildConfig.js); // 打包jsgulp.task('css', buildConfig.css); // 打包cssgulp.task('images', buildConfig.image); // 打包imagegulp.task('sources', gulp.series('html', gulp.parallel('js', 'css', 'images')));// 監聽文件變化gulp.task('watch', async () => { gulp.watch('src/views/*', gulp.series('html')); // 監聽HTML變化 gulp.watch('src/js/**', gulp.series('js')); // 監聽js變化 gulp.watch('src/css/*', gulp.series('css')); // 監聽css變化 gulp.watch('src/images/*', gulp.series('images')); // 監聽image變化});// buildif(process.env.NODE_ENV === 'dev') { gulp.task('dev', gulp.series('sources', 'server', 'watch'));} else { gulp.task('build', gulp.series('sources'));}

package.json

{"dependencies": { "@babel/core": "^7.4.5", "babel-preset-es2015": "^6.24.1", "gulp": "^4.0.2", "gulp-autoprefixer": "^6.1.0", "gulp-babel": "^8.0.0", "gulp-cache": "^1.1.2", "gulp-clean": "^0.4.0", "gulp-connect": "^5.7.0", "gulp-file-include": "^2.0.1", "gulp-imagemin": "^6.0.0", "gulp-jshint": "^2.1.0", "gulp-less": "^4.0.1", "gulp-md5-plus": "^1.0.3", "gulp-minify-css": "^1.2.4", "gulp-minify-html": "^1.0.6", "gulp-rename": "^1.4.0", "gulp-uglify": "^3.0.2", "gulp-util": "^3.0.8", "http-proxy-middleware": "^0.19.1", "http-server": "^0.11.1", "imagemin-pngquant": "^8.0.0", "jshint": "^2.10.2", "jsonfile": "^5.0.0", "webpack": "^4.35.2" }, "scripts": { "start": "NODE_ENV=dev gulp dev", "build": "NODE_ENV=prod gulp clean && gulp build", "serve": "http-server dist/static -p 3000" }, "devDependencies": {}}

要想獲取項目完整源碼和demo,請移步gulp4_multi_pages。

最後

該腳手架任然有需要完善的地方,比如如何兼容uglify和babel,md5需要使用兩次的情況,如果更好的解決方案,歡迎隨時交流。在腳手架選型上,也不一定非要用gulp,webpack,一般的經驗是傳統型的靜態網站適合用gulp,由於不需要編譯es6,所以有更小的體積,當然也可以用webpack,本文主要是給大家提供一使用gulp4搭建個腳手架的思路,希望能有所收穫。

相關焦點

  • 前端工程化之項目腳手架
    在軟體開發領域,如果把搭建項目想像成建造大型建築的話,腳手架就是為了方便大家快速進入業務邏輯的開發,一個好的腳手架能顯著提升工程效率,例如三大前端框架都提供了自己的腳手架工具:Angular 中的 @angular/cliVue 中的 @vue/cli
  • 如何做好一個Web前端開發工程師
    無論是後端開發、設計行業,還是零基礎行業,只要你對Web前端感興趣,就可以加入前端開發行業,這是一個報酬優厚的行業,在網際網路企業中不可或缺。很多人對 web前端都有濃厚的興趣,但卻不知道如何開始學習,今天就為大家推薦7步法幫助你成為 web前端開發工程師。
  • 一個前端工程師的十年
    十年之前,我還可以稱自己是個少年,十年後只能摸摸自己的大肚腩。感慨頗深,走過熟悉的街頭,人生又有多少個十年 。值此跨年之際,想給各位分享我做前端工程師的十年人生,希望對後浪們有所幫助。我學的是化學,但是因為喜歡編程,大學裡開始跟著中央電視臺搞起了網頁學習,當時玩的是網站三劍客(Dreamweaver,Fireworks,Flash)。我當時逢人便說自己是網站工程師,遭人嘲笑的同時也開始接觸到了人生第一個程式語言VB。從此一發不可收拾,開始真正的硬啃ASP。當時在學校信誓旦旦的接了一份兼職網站開發的活。
  • Web前端工程師具體是做什麼的?發展好嗎?
    前端開發工程師是Web前端開發工程師的簡稱,在國內真正被重視的不超過10年,並在國內各大公司裡都設立了專業的前端部門,也有一些基礎階段的「網站開發培訓」也隨之產生。1、什麼是Web前端Web前端開發技術是一個先易後難的過程,Web前端開發工程師,主要是實現客戶端(手機和電腦)上看到的頁面和一些交互效果(比如點擊,查看詳情)等。
  • 我這前端五年的總結,希望對你有幫助!
    算法:leetcode刷題我的個人規劃,當然不僅僅是一個前端工程師!中廠在中廠裡面,也許只有那麼一兩個牛逼的人。像技術經理、技術老大等。他們是我們值得學習的榜樣。但是他們有時候也會因為太忙。而忽略了內部團隊學習氛圍的建設。從而造成了,你覺得在這裡學習不到東西的感受。說一下我在中廠裡面學習到的一些東西吧。擔任面試官也許因為老大太忙,沒空。
  • 北大青鳥整理:一名web前端工程師需要必備哪些技術和工具?
    最近,有小夥伴私信留言讓我總結一下:「一個合格的web前端需要會什麼技術?」我想了半天,合格的web前端當然符合企業的用人要求啊!那麼一名web前端工程師需要必備哪些技術和工具?想要成為一個高薪高職的Web前端工程師並不容易,你不僅需要掌握專業的技能點,還要具備較多的項目經驗。優秀的Web前端工程師需要掌握哪些技術工具嗎?接下來就給大家一一介紹。
  • 前端開發需要學多長時間?剛學出來的前端工資多少-開課吧
    前端工程師,也叫Web前端開發工程師。他是隨著Web發展,細分出來的行業。尤其是現在網際網路時代,Web技術應用更加廣泛。網站、手機app、營銷H5等等都離不開Web技術。但是這只能說是一個基礎部分,找工作是找不到的。接下來就是需要再深入系統地學習,再學習一些前端自動化,一些流行的框架,還要稍微懂些node知識等,如果學習能力強並且自制力強的話,大概一共需要5個月的時間。當然這期間需要做大量的實踐與練習,來鞏固基礎知識。
  • 前端開發有哪些比較推薦學習的項目?
    前端開發有哪些比較推薦學習的項目?要找到這些項目可以通過如下方式:1、通常情況下,我們可以在github上面去搜索awesome javascript,很多優秀的JavaScript項目都被分門別類歸納好了。
  • 十大新興前端框架大盤點
    ramda近幾年來,前端面試的難度上了一個檔次,我們前端工程師要刷 LeetCode, 要手寫一大堆工具函數:函數節流、防抖、數組去重、扁平化,對象深拷貝等。每周都有周報,統計一共關了多少 issue,解決了多少問題,添加了多少新特性,讓大家用得非常安心。更不用說其官方運營的社區, http://taro-club.jd.com/, 可見官方在這方面投入非常大。5、Taro 擁有一個物料市場,號稱「讓每一個輪子產生價值」。物料就是一些組件,如果單純讓官方來做,肯定無法考慮到那麼巨細。
  • 為什麼前端是最適合設計師學習的編程技能「設計師的100個前端問題-001」
    這期分享是《設計師想知道的100個前端問題》系列內容的第一期,這個系列內容是為了讓更多設計師小夥伴或者是其他想學習前端的小夥伴快速了解前端是什麼,怎麼學,學什麼,還有就是哪怕就算你不想學習前端,也需要去了解的一些在設計工作中常會碰到的一些前端或者開發技術相關的知識,我會用儘量通俗易懂的方式讓你聽明白所有這些內容
  • 我的前端故事----優美的編輯器GitHub Atom
    sublime text,我之前也在使用,但是後來接觸到了Atom,就被它的高顏值深深的吸引了~~不愧是GitHub的工程師哦~審美就是高  Atom作為一個跨平臺的編輯軟體,安裝和使用都是十分的方便,剛剛接觸的同學也很容易在上面找到sublime text的影子,這非常方便像我這樣的人搬過來,那麼最基礎我就不介紹了,今天這篇就給剛剛接觸Atom的同學帶來一些常用的插件,你會發現,原來
  • 從後端開發轉職前端開發,我學到了什麼?
    以下是我從後端轉職前端開發至今的經驗:一切都與用戶界面和用戶體驗有關在後端,讓人最為擔心的就是數據結構,資料庫結構和性能,代碼架構,服務,以及開發前端工程師能理解並使用的強大API。前端則非常不同。在選擇符合需求和項目範圍的前端框架時,無論是React,Vue還是Angular,我都能選出正確的那一個。如果你想把UI組件分享給不同的項目及團隊,建議看看Bit的工具,看它能否幫到你。
  • web前端學習攻略
    web前端學習攻略第一階段:HTML+CSS:HTML進階、CSS進階、div+css布局、HTML+css整站開發、JavaScript基礎:Js基礎教程、js內置對象常用方法、常見DOM樹操作大全、ECMAscript、DOM、BOM、定時器和焦點圖。
  • Iconfont - 設計師/前端開發者必備的圖標管理工具
    介紹這是一個專門為設計師和前端開發者打造的在線工具。設計師將圖標上傳到 Iconfont,可以自定義下載多種格式的icon,也可將圖標轉換為字體,方便前端工程師自由調整與使用。通過這個免費的工具,設計師不僅可以瀏覽下載大量優秀設計師的圖標作品,還可以管理和展示自己設計的圖標。
  • 前端組件/庫打包利器rollup使用與配置實戰
    本文轉載自【微信公眾號:趣談前端,ID:beautifulFront】經微信公眾號授權轉載,如需轉載與原文作者聯繫目前主流的前端框架vue和react都採用rollup來打包,為了探索rollup的奧妙,接下來就讓我們一步步來探索,並基於rollup搭建一個庫打包腳手架,來發布自己的庫和組件。
  • 2020年4月4日詳細教你搭建react項目
    react屬於前端三大框架,作為一個前端程式設計師必須得會,也是自己高薪路上的墊腳石,前端框架日新月異,內容知識點不比後端少,本貼合適,沒有看過官方文檔的,對react不了解的人群快速搭建react項目,我以Windows7系統為例,話不多說,直接上圖文。
  • 前端渣渣的我再也不敢說我會寫React了
    本文轉載自【微信公眾號:前端人,ID:FrontendPeople】經微信公眾號授權轉載,如需轉載與原文作者聯繫前端這幾年的發展,經歷了移動網際網路時代的爆發,出現了以 Angular、React、Vue 為代表的三大前端框架,近日伴隨著 Vue
  • 五年前端大專學歷進騰訊啦!
    https://zhuanlan.zhihu.com/p/223459952從我開始做前端的時候,我就發誓我必須要進BAT,作為一個只是普通大專畢業的我,也沒有大廠的工作背景,其實對於30歲甚至35歲之後的發展,個人感覺是很受限制的,所以進入BAT是我一開始的目標,可能這就是曲線救國吧。
  • Web前端是什麼意思?朗沃Web前端包含哪些內容
    1、Web前端是什麼意思Web前端是網站前臺部分,運行在PC端,移動端等瀏覽器上展現給用戶所瀏覽的網頁。用我們的話來說,前端就是網頁給訪問網站的人看的內容和頁面,Web前端開發意思就是這些內容的製作,也就是代碼的實現。
  • 水琴鈴(北京)聘:前端/後端/web工程師/特效/UI/劇情架構師
    有意的童鞋可以先搜索下『魔女兵器』相關視頻,覺得遊戲對口味再考慮與吾籤訂契約成為魔法少女(ಠ౪ಠ將靈魂出賣給路西法)什麼的也不遲嘛~~ 招聘需求如下: U3D前端研發工程師職責具備團隊管理經驗 工作地點:北京國貿 待遇:16K+請將簡歷發至:info@shuiqinling.com 後臺系統開發工程師職責1. 使用Golang設計和開發遊戲伺服器端,包括數據結構、業務邏輯和通信協議2.