前言
如今我们开发web网页的方式主要有几种,使用
vue-cli、create-react-app、webpack、不借助构建工具
等实现单页或多页网站。“工欲善其事,必先利其器”,前三种方式无疑能满足我们开发网页的绝大部分需求,但在某些情况下,比如前后端不分离(jsp、php、tpl等嵌套后端语言的方式),以及单纯地开发一些静态页(活动页、帮助手册等),使用gulp搭建一个轻量级的前端开发环境是一个选择。
gulp相对上手简单,有经验的前端也都比较熟悉,这里不打算一步步地介绍gulp开发环境的搭建,而是分享一下实际使用gulp的代码及思路。
实现哪些功能
使用gulp的目的是实现自动化构建,提升开发效率、代码质量,所以有以下一些目标。
- 压缩html、css、js、图片
- 编译ES6、less/scss
- 补全css前缀
- px转rem
- 静态资源缓存控制
- 静态服务器
- 代码检查
实际上gulp能做到的还有更多,不过出于开发静态页的目的,这里只罗列了一些常用功能。
代码
基本目录如下
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIwczX0xiRGZkRGZ0Xy9GbvNGL2EzXlpXazxyMJRVT5llaNlXT6hFeGNDTwYVbiVHNHpleO1GTulzRilWO5xkNNh0YwIFSh9Fd4VGdsATMfd3bkFGazxyaHRGcWdUYuVzVa9GczoVdG1mWfVGc5RHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5SNzMzM0EjM1ITMxkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
gulpfile.js主要代码
静态服务器
gulp.task('server', done => {
connect.server({
root: 'dist',//根目录
livereload: true,//自动更新
port: 9090//端口
})
done();
});
压缩html
gulp.task('html', function () {
return gulp.src('src/*.html')
.pipe(htmlmin({ collapseWhitespace: true }))
.pipe(gulp.dest('dist'))
.pipe(connect.reload())
})
编译并压缩css
gulp.task('css', done => {
var processors = [px2rem({ remUnit: 100 })];
gulp.src('src/less/**/*.less') //获取所有less文件路径
.pipe(less()) //执行less
.pipe(autoprefixer({//补全前缀
overrideBrowserslist: [
"Android 4.1",
"iOS 7.1",
"Chrome > 31",
"ff > 31",
"ie >= 8"
]
}))
.pipe(postcss(processors))//px转rem tips: 如果某个px不转换,可使用大写代替,类似1PX
.pipe(minifyCss())
.pipe(gulp.dest('dist/css'))
.pipe(connect.reload())
done();
});
编译并压缩js
gulp.task('js', function () {
return gulp.src('src/js/**/*.js')
//.pipe(jshint())//检查代码
.pipe(babel({//编译ES6
presets: ['@babel/env']
}))
.pipe(uglify())//压缩js
.pipe(gulp.dest('dist/js'))
.pipe(connect.reload())
})
压缩图片
gulp.task('images', function () {
return gulp.src('src/images/**/*.+(png|jpg|jpeg|gif|svg)')
.pipe(imagemin())
.pipe(gulp.dest('dist/images'))
});
监控文件变化
gulp.task('watcher', done => { //监听变化
gulp.watch('src/*.html', gulp.series('html'));
gulp.watch('src/less/**/*.less', gulp.series('css'));
gulp.watch('src/js/**/*.js', gulp.series('js'));
gulp.watch('src/images/**/*', gulp.series('images'));
done();
})
生成带hash值的文件名及路径
这里还使用了
gulp-rev-delete-original
删除旧文件。
gulp.task("hash", done => {
gulp
.src("dist/**")
.pipe(
RevAll.revision({
dontRenameFile: [/\.html$/]
})
)
.pipe(revdel({
exclude: function (file) {
if (/\.html$/.test(file.name)) {
return true; //if you want to exclude the file from being deleted
}
}
}))
.pipe(gulp.dest("dist"))
done();
});
gulp命令
打开本地服务器,以及打包文件。
// 初始化
gulp.task('init', gulp.series('clean', gulp.parallel('html', 'css', 'js', 'images')));
// 开发
gulp.task('default', gulp.series('init', 'server', 'watcher'));
// 打包
gulp.task('build', gulp.series('hash'));
可以看出上面的代码比较简单,因为初衷是做一些简单的静态页,所以并没有做得比较复杂,监控文件变化编译至dist目录,再由gulp-rev-all生成hash文件名。
前后端不分离的情况
这里需要区分前后端不分离的情况,由于公司的技术不升级,或者需要维护老项目,就要应付前后端不分离的场景。比如页面是jsp、php文件,这时静态页跟实际页面并没有直接对应关系,每次gulp打包后,gulp-rev-all会重新生成带hash的文件和路径,并且不支持
test.css?v=123
这种方式,这样全部手动复制到项目目录并不实际,只能放弃gulp-rev-all(
build
),并且移除代码压缩。
值得一提的是,前后端不分离可以用后端语言进行资源的缓存控制,例如使用php读取文件的修改日期来做版本号。
function autoVersion($file) {
if( file_exists($_SERVER['DOCUMENT_ROOT'].$file) ) {
$ver = filemtime($_SERVER['DOCUMENT_ROOT'] . $file);
} else {
$ver = 1;
}
return $file .'?v=' .$ver;
}
此外,应对前后端不分离应该还有一种解决方案,借助构建工具直接生成后端所需的模板文件(如index.tpl),这里暂不讨论。
最后
这些是根据工作经验总结出来的,虽然当下使用或基于webpack开发单页是主流,但在某些覆盖不到的场景下进行一些梳理还是有必要的。
源码地址:gulp-util,另外附上一个webpack多页脚手架webpack-multiple-entry,这是作者fork别人的项目来修改的,比较简单实用,感兴趣的小伙伴可以参考下。