blog
blog copied to clipboard
2019年Gulp自动化压缩合并构建的解决方案
虽然网上有很多的 gulp 构建文章,但是很多都已经随着 gulp 插件的更新无法运行了。因此,我写了这个比较简单的构建方案。本文基于 gulp 最新的 4.0.2 版本进行了修改。现在前端组件化项目大多是基于 webpack 进行构建,但是有一个零散的小业务,静态页面之类的,使用 gulp 反而会更加简单方便。
如果还不熟悉 gulp 的插件,可以阅读上一篇文章:精通gulp常用插件
这个方案主要是为了实现es6转es5、js/css的压缩合并、自动添加版本号和压缩html。
- gulp-babel es6转es5
- gulp-csso 压缩优化css
- gulp-uglify 压缩js
- gulp-htmlmin 压缩html
- gulp-filter 过滤文件
- gulp-rev-all 生成版本号
主要通过上面插件实现功能,其他插件配合使用。
安装相关依赖:npm i gulp gulp-uglify gulp-htmlmin gulp-useref gulp-csso gulp-filter gulp-rev-all gulp-base64 gulp-autoprefixer del gulp-babel @babel/core @babel/preset-env -D
// gulpfile.js
const { series, parallel, src, dest } = require('gulp');
const uglify = require('gulp-uglify');
const htmlmini = require('gulp-htmlmin');
const useref = require('gulp-useref');
const csso = require('gulp-csso');
const filter = require('gulp-filter');
const babel = require('gulp-babel');
const RevAll = require('gulp-rev-all');
const base64 = require('gulp-base64');
const autoprefixer = require('gulp-autoprefixer');
const del = require('del');
// 压缩html配置
const options = {
removeComments: true,
collapseWhitespace: true,
collapseBooleanAttributes: true,
removeEmptyAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
minifyJS: true,
minifyCSS: true
};
const defaultTask = cb => {
const jsFilter = filter('**/*.js', { restore: true });
const cssFilter = filter('**/*.css', { restore: true });
const htmlFilter = filter(['**/*.html'], { restore: true });
src('*.html')
.pipe(useref()) // 解析html中的构建块
.pipe(jsFilter) // 过滤所有js
.pipe(babel({
presets: ['@babel/env'],
sourceType: 'script'
}))
.pipe(uglify()) // 压缩js
.pipe(jsFilter.restore)
.pipe(cssFilter) // 过滤所有css
.pipe(autoprefixer()) // 添加css前缀
.pipe(base64())
.pipe(csso()) // 压缩优化css
.pipe(cssFilter.restore)
.pipe(RevAll.revision({ // 生成版本号
dontRenameFile: ['.html'], // 不给 html 文件添加版本号
dontUpdateReference: ['.html'] // 不给文件里链接的html加版本号
}))
.pipe(htmlFilter) // 过滤所有html
.pipe(htmlmini(options)) // 压缩html
.pipe(htmlFilter.restore)
.pipe(dest('./dist'))
.on('error', function (err) {
throw new Error(err.toString())
})
cb();
}
const delDist = cb => {
del.sync(['./dist']);
cb();
}
const copyAssets = cb => {
src('static/img/**').pipe(dest('./dist/static/img/'));
cb();
}
exports.default = series(delDist, parallel(defaultTask, copyAssets));
在html中,我们需要先定义好构建块。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>gulp自动化构建解决方案</title>
<!-- build:css static/css/index.css --> // 定义了构建后引用的css路径
<link rel="stylesheet" href="static/css/common.css"/>
<link rel="stylesheet" href="static/css/index.css"/>
<!-- endbuild -->
</head>
<body>
......
<!-- build:js static/js/index.js --> // 定义了构建后引用的js路径
<script src="static/js/jquery.js"></script>
<script src="static/js/common.js"></script>
<script src="static/js/index.js"></script>
<!-- endbuild -->
</body>
</html>
执行构建完成后,会生成 dist 文件夹,目录为:
|-dist
| |-static
| |-css
| |-index.96cf44da.css
| |-img
| |-js
| |-index.42ce3282.js
| |-index.html
构建完的index.html,我们忽略压缩的html,完成了压缩合并添加版本号等功能。
// dist/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>gulp自动化构建解决方案</title>
<link rel="stylesheet" href="static/css/index.96cf44da.css"/>
</head>
<body>
......
<script src="static/js/index.42ce3282.js"></script>
</body>
</html>
对于图片这种静态资源发布到cdn的话,是不是也要生成md5指纹呢?
@2lei 是啊,不然的话你图片更改之后,在页面访问一直是访问到缓存的未改之前的图片
@lin-xin 你好 这个 gulpfile.js 可以完善一下吗?
@vincent-cong 这个哪里有问题吗?
@lin-xin 打包完了 并没有dist文件夹。。。。这个是什么原因?这个你可以出一个案列吗?非常感谢。
@vincent-cong 像上面涉及到的路径,你要按照你实际项目的路径修改一下
@lin-xin
var jsFilter = filter('src/js/.js',{restore:true}),
cssFilter = filter('src/js/.css',{restore:true}),
htmlFilter = filter(['src/.html'],{restore:true});
gulp.src('src/.html')
加过了,也没用。。。你可以自己试试看
我的文件目录是 src --js --aa.js src --css-aa.css src --aa.html *.js *.css *.html 星号都是有的
@vincent-cong 我没有你的文件我怎么试呢,我这边是没问题的哦
@lin-xin 好吧 你那是好的,那估计是我的目录不对。。。我再按照你上面的目录弄一下吧,灰常感谢。如果方便的话可以加个例子么?
怎么html压缩 语句不起作用啊?
@dumuchenglin123 压缩的代码你注释掉了。用了 gulpif( ) 你的condition ,你有定义吗?condition 为true时才会执行后面的压缩。
@lin-xin 为什么要进行文件过滤呢?
@MagicHacker 因为 gulp.src('/*.html') 源文件是针对 html 的,所以过滤出这个html里面引用的js和css进行操作
@lin-xin ok,明白了,谢谢。没注意到路径是/*.html的。我刚用这个东西不久,平时都是单独定义任务的。
gulp.task('test', function () {
var jsFilter = filter(['src/js/**/*.js', '!src/js/libs/**/*.js'],{restore:true}),
cssFilter = filter('src/css/**/*.css',{restore:true}),
htmlFilter = filter(['src/html/**/*.html'],{restore:true});
gulp.src('src/html/**/*.html')
.pipe(useref()) // 解析html中的构建块
.pipe(jsFilter) // 过滤所有js
.pipe(uglify()) // 压缩js
.pipe(jsFilter.restore)
.pipe(cssFilter) // 过滤所有css
.pipe(minifycss()) // 压缩优化css
.pipe(cssFilter.restore)
.pipe(RevAll.revision({ // 生成版本号
dontRenameFile: ['.html'], // 不给 html 文件添加版本号
dontUpdateReference: ['.html'] // 不给文件里链接的html加版本号
}))
.pipe(htmlFilter) // 过滤所有html
.pipe(htmlmini()) // 压缩html
.pipe(htmlFilter.restore)
.pipe(gulp.dest('dist/'))
})
为什么我过滤所有js之后,后面进行压缩,好像没有执行这个操作?大神,帮我看看哪里写错了
@Pulset html里有没有加上 < ! -- build:css xxx --> < ! -- endbuild -->
@lin-xin 加上了,js、css也能合并之后输出,但是都没有压缩
@Pulset 那是不是忘了安装 gulp-uglify 等压缩插件还是引入的出了问题
@lin-xin 原来是路径问题,改成这样就行了
var jsFilter = filter('**/*.js', { restore: true }),
cssFilter = filter('**/*.css', { restore: true }),
htmlFilter = filter('**/*.htm', { restore: true });
请问博主,针对多页面有什么好的解决方案吗,除了index.html 我还有htm/**/*.html等页面 自动化压缩打版本加hash自动替换,有什么好的解决方法吗
@BiYuqi 多页面也适合用这个方案的
那页面中的图片该怎么处理勒?