<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>

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

          共 9668字,需瀏覽 20分鐘

           ·

          2020-12-20 23:52



          冬至?xí)r節(jié), 程序員加油!


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

          前言

          由于本文重點(diǎn)是介紹gulp4.0搭建腳手架的思路,相關(guān)插件的用法以及項(xiàng)目結(jié)構(gòu)的設(shè)計(jì),由于gulp的基本用法很簡單,如果不熟悉可以移步官網(wǎng)自行研究學(xué)習(xí)。該腳手架的設(shè)計(jì)思路和功能如下:

          同時(shí)為了提高開發(fā)環(huán)境的效率,這里我們參考webpack的配置,區(qū)分開發(fā)環(huán)境和生產(chǎn)環(huán)境,在接下來將會(huì)具體介紹。

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

          • gulp-jshint ——js語法檢測
          • gulp-util ——終端控制臺(tái)打印自定義錯(cuò)誤信息
          • http-proxy-middleware ——設(shè)置代理,配合gulp-connect使用
          • gulp-less ——將less編譯成css
          • gulp-file-include ——用于文件模塊化導(dǎo)入,如用include的方式導(dǎo)入公共部分
          • gulp-connect ——用于啟動(dòng)本地服務(wù)器
          • gulp-clean ——清理目錄
          • gulp-uglify --壓縮js
          • gulp-minify-css ——壓縮css
          • gulp-autoprefixer ——自動(dòng)添加瀏覽器前綴
          • imagemin-pngquant ——png圖片壓縮
          • gulp-imagemin ——圖壓縮
          • gulp-cache ——設(shè)置gulp打包的緩存,一般用于img
          • gulp-md5-plus ——將文件名進(jìn)行md5處理便于打包更新

          當(dāng)然gulp還有很多常用的插件可以更好的為我們的項(xiàng)目服務(wù),大家也可以整合自己的插件讓項(xiàng)目更加完善。

          項(xiàng)目目錄設(shè)計(jì)

          1.src目錄,即我們開發(fā)項(xiàng)目時(shí)的源目錄,具體結(jié)構(gòu)如下:

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

          2. dist目錄,即輸出的目錄,具體結(jié)構(gòu)如下:

          可以看到我們會(huì)看到src打包后的目錄對應(yīng)static目錄,為什么我們會(huì)加一層static呢?我的設(shè)計(jì)是如果項(xiàng)目使用node等服務(wù)層框架,我們可以用gulp一并打包放入dist下,這樣dist就是一個(gè)完整的包括前后端服務(wù)的項(xiàng)目目錄了,當(dāng)然大家也可以直接將src打包后的文件和文件夾直接放到dist下,根具業(yè)務(wù)需求靈活設(shè)計(jì)吧。

          在這里我要說一點(diǎn),由于筆者親測gulp-md5-plus有時(shí)候打包不穩(wěn)定,可能不會(huì)給html自動(dòng)添加對應(yīng)的md5后綴,所以筆者在這塊做了特殊的處理,如果大家在工作中有更好的方案,可以及時(shí)和筆者溝通交流。

          3. gulpfile文件配置

          由于我們要區(qū)分開發(fā)環(huán)境和生產(chǎn)環(huán)境,所以這里我們使用兩個(gè)不同的配置文件,根據(jù)NODE_ENV來區(qū)分用哪個(gè)文件。

          我們將配置文件統(tǒng)一放到build目錄下,config為公共配置文件,gulp.dev.js和gulp.prod.js分別為開發(fā)和生產(chǎn)環(huán)境配置文件。我們整體的目錄結(jié)構(gòu)如下:

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

          1. config.js
          module.exports?=?{
          ????dist:?'./dist/static',??//?配置構(gòu)建目錄
          }
          1. gulp.dev.js
          const?gulp?=?require('gulp');
          //?js
          const?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');

          //?css
          const?Less?=?require('gulp-less');??????????????//?編譯less

          //?html
          const?FileInclude?=?require('gulp-file-include');?//?文件模塊化

          //?server
          const?Connect?=?require('gulp-connect');????????//引入gulp-connect模塊?

          const?Clean?=?require('gulp-clean');????????????//?清理目錄

          //?配置文件
          const?config?=?require('./config');
          const?{?dist?}?=?config;

          //?html
          async?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())
          }

          //?css
          async?function?css()?{
          ????return?await?gulp.src('src/css/*.less')
          ????.pipe(Less())???????//編譯less
          ????.pipe(gulp.dest(dist?+?'/css'))?//當(dāng)前對應(yīng)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+可以單獨(dú)配置
          ????//?compilerJS.run(function(err,?stats)?{
          ????//?????if(err)?throw?new?Gutil.PluginError("webpack:js",?err);
          ????//?????Gutil.log("[webpack]",?stats.toString({
          ????//?????????colors:?true
          ????//?????}));
          ????//?????cb()
          ????//?});
          }

          //?image
          async?function?image()?{
          ????return?await?gulp.src('src/images/*')
          ????.pipe(gulp.dest(dist?+?'/images'));
          }

          //?clean?dir
          async?function?clean()?{
          ????//?不設(shè)置allowEmpty:?true會(huì)報(bào)File?not?found?with?singular?glob
          ????return?await?gulp.src(dist,?{allowEmpty:?true}).pipe(Clean());
          }

          //?服務(wù)器函數(shù)
          async?function?server()?{
          ????Connect.server({
          ????????root:dist,?//根目錄
          ????????//?ip:'192.168.11.62',//默認(rèn)localhost:8080
          ????????livereload:true,?//自動(dòng)更新
          ????????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
          }
          1. gulp.prod.js
          const?gulp?=?require('gulp');
          //?const?Rename?=?require('gulp-rename');??????????//?重命名
          //?js
          const?Uglify?=?require('gulp-uglify');??????????//?壓縮js
          //?const?Babel?=?require('gulp-babel');
          //?css
          const?Minifycss?=?require('gulp-minify-css');???//?壓縮css
          const?Less?=?require('gulp-less');??????????????//?編譯less
          const?Autoprefixer?=?require('gulp-autoprefixer');??//?瀏覽器前綴
          //?html
          const?MinifyHtml?=?require("gulp-minify-html");?//壓縮html
          const?FileInclude?=?require('gulp-file-include');?//?文件模塊化
          //?image
          const?Imagemin?=?require('gulp-imagemin');
          const?Pngquant?=?require('imagemin-pngquant');??//png圖片壓縮插件
          const?Cache?=?require('gulp-cache');?

          const?Clean?=?require('gulp-clean');????????????//?清理目錄

          //?md5?發(fā)版本的時(shí)候?yàn)榱吮苊鉃g覽器讀取了舊的緩存文件,需要為其添加md5戳
          const?md5?=?require("gulp-md5-plus");

          const?config?=?require('./config');
          const?{?dist?}?=?config;
          //?html
          async?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))?//?拷貝?
          }

          //?css
          async?function?css()?{
          ????return?await?gulp.src('src/css/**')
          ????.pipe(Less())???????//編譯less
          ????.pipe(Autoprefixer({
          ????????cascade:?true,?//是否美化屬性值?默認(rèn):true 像這樣:
          ????????//-webkit-transform:?rotate(45deg);
          ????????//????????transform:?rotate(45deg);
          ????????remove:?true?//是否去掉不必要的前綴?默認(rèn):true
          ????}))
          ????.pipe(Minifycss({???//?壓縮css
          ????????//類型:Boolean 默認(rèn):true [是否開啟高級優(yōu)化(合并選擇器等)]
          ????????advanced:?true,
          ????????//保留ie7及以下兼容寫法?類型:String 默認(rèn):''or'*'?[啟用兼容模式;?'ie7':IE7兼容模式,'ie8':IE8兼容模式,'*':IE9+兼容模式]
          ????????compatibility:?'',
          ????????//類型:Boolean 默認(rèn):false [是否保留換行]
          ????????keepBreaks:?false,
          ????????//保留所有特殊前綴?當(dāng)你用autoprefixer生成的瀏覽器前綴,如果不加這個(gè)參數(shù),有可能將會(huì)刪除你的部分前綴????????
          ????????keepSpecialComments:?'*'
          ????}))
          ????.pipe(gulp.dest(dist?+?'/css'))
          ????.pipe(md5(10,?dist?+?'/*.html',?{
          ????????mappingFile:?'manifest.json',
          ????????connector:?'.'?//?文件名和hash的連接符
          ????}))
          ????.pipe(gulp.dest(dist?+?'/css'))?//當(dāng)前對應(yīng)css文件
          }

          //?js
          async?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'))?//?拷貝
          }

          //?image
          async?function?image()?{
          ????return?await?gulp.src('src/images/*')
          ????.pipe(Cache(Imagemin({
          ????????optimizationLevel:?5,?//類型:Number ?默認(rèn):3 ?取值范圍:0-7(優(yōu)化等級)
          ????????progressive:?true,?//類型:Boolean 默認(rèn):false 無損壓縮jpg圖片
          ????????interlaced:?true,?//類型:Boolean 默認(rèn):false 隔行掃描gif進(jìn)行渲染
          ????????multipass:?true,?//類型:Boolean 默認(rèn):false 多次優(yōu)化svg直到完全優(yōu)化
          ????????svgoPlugins:?[{removeViewBox:?false}],//不要移除svg的viewbox屬性
          ????????use:?[Pngquant()]?//使用pngquant深度壓縮png圖片的imagemin插件
          ????})))
          ????.pipe(gulp.dest(dist?+?'/images'));
          }


          //?clean?dir
          async?function?clean()?{
          ????//?不設(shè)置allowEmpty:?true會(huì)報(bào)File?not?found?with?singular?glob
          ????return?await?gulp.src(dist,?{allowEmpty:?true}).pipe(Clean());
          }



          module.exports?=?{
          ????html,
          ????css,
          ????js,
          ????image,
          ????clean
          }
          1. gulpfile.js
          const?gulp?=?require('gulp');

          //?根據(jù)環(huán)境引入不同的配置文件
          let?buildConfig;
          if(process.env.NODE_ENV?===?'dev')?{
          ????buildConfig?=?require('./build/gulp.dev');
          ????gulp.task('server',?buildConfig.server);??//?本地服務(wù)
          ????
          }?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);??????//?打包html
          gulp.task('js',?buildConfig.js);??????????//?打包js
          gulp.task('css',?buildConfig.css);????????//?打包c(diǎn)ss
          gulp.task('images',?buildConfig.image);???//?打包image
          gulp.task('sources',?gulp.series('html',?gulp.parallel('js',?'css',?'images')));


          //?監(jiān)聽文件變化
          gulp.task('watch',?async?()?=>?{
          ????gulp.watch('src/views/*',?gulp.series('html'));?//?監(jiān)聽HTML變化
          ????gulp.watch('src/js/**',?gulp.series('js'));?//?監(jiān)聽js變化
          ????gulp.watch('src/css/*',?gulp.series('css'));?//?監(jiān)聽css變化
          ????gulp.watch('src/images/*',?gulp.series('images'));?//?監(jiān)聽image變化
          });

          //?build
          if(process.env.NODE_ENV?===?'dev')?{
          ????gulp.task('dev',?gulp.series('sources',?'server',?'watch'));
          }?else?{
          ????gulp.task('build',?gulp.series('sources'));
          }


          1. 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":?{}
          }

          要想獲取項(xiàng)目完整源碼和demo,請移步gulp4_multi_pages。

          最后

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




          點(diǎn)個(gè)在看 你最好看




          瀏覽 56
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  淫香淫色综合 | 欧美V亚洲V日韩v | 欧美黄色大片一级a | 玖玖视频在线观看 | 91视频盛宴 |