用 webpack 4.0 擼單頁/多頁腳手架 (jquery, react, vue, typescript)
前言
由于本文重點是介紹gulp4.0搭建腳手架的思路,相關插件的用法以及項目結構的設計,由于gulp的基本用法很簡單,如果不熟悉可以移步官網自行研究學習。該腳手架的設計思路和功能如下:
腳手架用到的第三方插件介紹
- gulp-jshint ——js語法檢測
- gulp-util ——終端控制臺打印自定義錯誤信息
- http-proxy-middleware ——設置代理,配合gulp-connect使用
- gulp-less ——將less編譯成css
- gulp-file-include ——用于文件模塊化導入,如用include的方式導入公共部分
- gulp-connect ——用于啟動本地服務器
- gulp-clean ——清理目錄
- gulp-uglify --壓縮js
- gulp-minify-css ——壓縮css
- gulp-autoprefixer ——自動添加瀏覽器前綴
- imagemin-pngquant ——png圖片壓縮
- gulp-imagemin ——圖壓縮
- gulp-cache ——設置gulp打包的緩存,一般用于img
- gulp-md5-plus ——將文件名進行md5處理便于打包更新
當然gulp還有很多常用的插件可以更好的為我們的項目服務,大家也可以整合自己的插件讓項目更加完善。
項目目錄設計
1.src目錄,即我們開發項目時的源目錄,具體結構如下:
2. dist目錄,即輸出的目錄,具體結構如下:
在這里我要說一點,由于筆者親測gulp-md5-plus有時候打包不穩定,可能不會給html自動添加對應的md5后綴,所以筆者在這塊做了特殊的處理,如果大家在工作中有更好的方案,可以及時和筆者溝通交流。
3. gulpfile文件配置
由于我們要區分開發環境和生產環境,所以這里我們使用兩個不同的配置文件,根據NODE_ENV來區分用哪個文件。
腳手架完整源碼(部分插件和配置會給出詳細注釋)
- config.js
module.exports = {dist: './dist/static', // 配置構建目錄
}
復制代碼
- 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')) //當前對應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()// });
}// image
async function image() {return await gulp.src('src/images/*').pipe(gulp.dest(dist + '/images'));
}// clean dir
async function clean() {// 不設置allowEmpty: true會報File not found with singular globreturn await gulp.src(dist, {allowEmpty: true}).pipe(Clean());
}// 服務器函數
async function server() {Connect.server({root:dist, //根目錄// ip:'192.168.11.62',//默認localhost:8080livereload: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'); // 重命名
// 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 發版本的時候為了避免瀏覽器讀取了舊的緩存文件,需要為其添加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, //是否美化屬性值 默認: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文件
}// 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 默認: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 dir
async function clean() {// 不設置allowEmpty: true會報File not found with singular globreturn 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); // 打包html
gulp.task('js', buildConfig.js); // 打包js
gulp.task('css', buildConfig.css); // 打包css
gulp.task('images', buildConfig.image); // 打包image
gulp.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變化
});// build
if(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搭建個腳手架的思路,希望能有所收獲。
更多推薦
- 如何用不到200行代碼寫一款屬于自己的js類庫)
- 讓你瞬間提高工作效率的常用js函數匯總(持續更新)
- 一張圖教你快速玩轉vue-cli3
- 3分鐘教你用原生js實現具有進度監聽的文件上傳預覽組件
- 3分鐘教你用原生js實現具有進度監聽的文件上傳預覽組件
- 使用Angular8和百度地圖api開發《旅游清單》
- js基本搜索算法實現與170萬條數據下的性能測試
- 《前端算法系列》如何讓前端代碼速度提高60倍
- 《前端算法系列》數組去重
- vue高級進階系列——用typescript玩轉vue和vuex
- 前端三年,談談最值得讀的5本書籍
歡迎關注下方公眾號,獲取更多前端知識精粹和學習社群:
回復學習路徑,將獲取筆者多年從業經驗的前端學習路徑的思維導圖