gulp自动化构建工作流——项目常用配置
写在最前
在项目中,除了使用Mvvm框架开发一个完整的app外,往往还有在原生app内部嵌入多个灵散H5页面的需求。
在MVVM框架中,因为有vue-cli来实现项目结构的搭建,其中搭配webpack进行了开发的自动化构建配置,使开发过程中能过专注于业务逻辑,而不用多去考虑代码压缩,图片压缩,及替换等。
对于灵散的H5页面应用,使用gulp进行自动化构建,可以尽可能的压缩代码,压缩资源大小,从而使用用户能快速的访问到内容,并节省请求带宽。
gulp是一款成熟的自动化构建工具,也有很多好用的插件。以下总结在项目中通过gulp配置自动化工作流来提升工具效率的过程及注意点。
开发前准备
以一个新的需求为例(如:在app内部的不同入口嵌入多个互不相关的H5应用页面,包括静态的,也包括前后交互的)
工具准备
使用gulp,定当先安装gulp(两次安装:1. 全局安装,2.所在项目中以开发依赖安装)
# 1. 先全局安装
npm i -g gulp
# 项目最最开始(从0到1),创建一个项目文件并初始化
npm init
# 2. 在项目中以开发依赖安装(-D 为--save-dev缩写)
npm i -D gulp
# 3. 项目根目录创建gulp配置文件gulpfile.js(gulp工作方式的关键)
var gulp = require('gulp')
gulp.task('default',function(){
// 默认任务的代码
})
gulp.task('test',function(){...})
# 4. 运行gulp(以CMD命令为例)_直接gulp时,默认是直接名为'default'的任务
gulp test
gulp配置关键步骤
通过以上初始化一个项目后并手动创建开发目录,项目目录文件如下:
|_ package.json
|_ gulpfile.js
|_ img
|_ css
|_ js
|_ node_modules
|_ index.html
|_ page2.html
- 以上为项目目录结构,下一步需求:1. 通过gulp构建一个本地服务,运行此项目。2. 使用gulp压缩整合html,css,img,js。使项目变得精简,运行提速。
gulp常用方法(gulpfile.js为例)
- gulp.task() 创建gulp任务
- gulp.src() gulp任务源文件查找
- gulp.pipe() gulp工作流
- gulp.dest() gulp任务输出
1. 创建第一个gulp任务 (gulp-connect)
- 需求:使用gulp创建一个本地服务
- gulp插件: gulp-connect
- 插件API地址: https://www.npmjs.com/package/gulp-connect
# 安装插件依赖
npm i -D gulp-connect
# 配置gulpfile.js
// 导入依赖
var gulp = require('gulp'),
connect = requiire('gulp-connect');
// dev服务任务
gulp.task('dev',function(){
connect.server({
port:8090 //设置服务商品
})
})
# 命令终端中执行gulp命令
gulp dev
# 结果
[15:03:37] Using gulpfile D:\1-workspace\tempGulp\gulpfile.js
[15:03:37] Starting 'dev'...
[15:03:37] Starting server...
[15:03:37] Finished 'dev' after 19 ms
[15:03:37] Server started http://localhost:8090
[15:03:37] Running server
其他gulp-connect中的配置项说明:
- root: 设置服务的启动根目录,当启动服务时,默认到此目录文件中找
- livereload: 热加载(通过设置,当修改html,或css时,浏览器预览实时刷新效果)
- port: 服务端口
- host: 服务域名,默认为localhost,可以改为本机ip
2. 构建热加载服务
- 需求:当修改项目中的html,或者stylus文件时,项目能够自动刷新浏览器,实现实时预览功能
- 插件:gulp-connect(服务),gulp-less
- gulp-less:https://www.npmjs.com/package/gulp-less
var gulp = require('gulp'),
connect = require('gulp-connect'),
less = require('gulp-less');
// 基本服务
gulp.task('dev', function () {
connect.server({
port: 8060,
livereload: true
})
})
// html热加载
gulp.task('html', function () {
gulp.src('./*.html')
.pipe(gulp.dest('./myproject'))
.pipe(connect.reload())
})
// less的编译及加载
gulp.task('less', function () {
gulp.src('./less/*.less')
.pipe(less()) //less编译为css
.pipe(gulp.dest('./css'))
.pipe(connect.reload())
})
// 观察
gulp.task('watch', function () {
gulp.watch(['./*.html'], ['html'])
gulp.watch(['./less/*.less'],['less'])
})
gulp.task('default',['dev','watch'])
3.压缩代码,整合文件引用
- 需求:将开发中的js,css,html进行压缩处理,使文件更小,访问更快速
- 插件:gulp-useref(用于整合引用的资源),gulp-uglify(压缩js),gulp-clean-css(压缩css),gulp-if(条件判断)
- API地址: https://www.npmjs.com/package/gulp-useref
# 1.配置gulp
var gulp = require('gulp'),
connect = require('gulp-connect'),
less = require('gulp-less'),
useref = require('gulp-useref'),
uglify = require('gulp-uglify'),
minifyCss = require('gulp-clean-css'),
gulpif = require('gulp-if');
gulp.task('dev', function () {
connect.server({
port: 8060,
})
})
gulp.task('compress', function () {
return gulp.src('./*.html')
.pipe(useref())
.pipe(gulpif('*.js',uglify()))
.pipe(gulpif('*.css',minifyCss()))
.pipe(gulp.dest('./dist')) //输出目录
})
# 2. 在html中引用位置对应添加整合注释
<!-- build:js js/main.min.js -->
<script src="js/zepto.js"></script>
<script src="js/main.js"></script>
<!-- endbuild -->
# 3. 最终变为
<script src="js/main.min.js"></script>
gulp-useref的作用?
- gulp-useref 并不会压缩代码,但可以将多个文件整合为一个(将html中零碎的引入合并成一个文件)。如下:
- 注意:通过html中的注释能够指示合并后的文件命名。
# 原文件
<html>
<head>
//如下:将两个css合并后,成为combined.css
<!-- build:css css/combined.css -->
<link href="css/one.css" rel="stylesheet">
<link href="css/two.css" rel="stylesheet">
<!-- endbuild -->
</head>
<body>
<!-- build:js scripts/combined.js -->
<script type="text/javascript" src="scripts/one.js"></script>
<script type="text/javascript" src="scripts/two.js"></script>
<!-- endbuild -->
</body>
</html>
# 构建后
<html>
<head>
<link rel="stylesheet" href="css/combined.css"/>
</head>
<body>
<script src="scripts/combined.js"></script>
</body>
</html>
4. 压缩图片
- 需求:将项目中的图片压缩后输出
- 插件:gulp-imagemin
var imagemin = require('gulp-imagemin')
gulp.task('img',function(){
gulp.src(['./img/*'])
.pipe(imagemin())
.pipe(gulp.dest('./dist'))
})
5. 文件清除 gulp-clean
- 需求:每次打包项目文件后会新成新的文件,旧文件就应该删除。
- 插件: gulp-clean
var clean = require('gulp-clean')
gulp.task('clean',function(){
return gulp.src('./myproject')
.pipe(clean())
})
6. 多任务依次执行 gulp-sequence
- 场景:当需要多个任务依次执行
- 插件: gulp-sequence
var gulpSequenc = require('gulp-sequence')
gulp.task('build',gulpSequence(['clean','compress','imagemin']))
7. 给压缩文件添加 md5后缀
- 场景:静态资源在浏览器中往往会有缓存,这会导致当更新了静态资源后,浏览器中的呈现效果还是以前一样(因为缓存)。而通过添加MD5后缀,使每次更新的文件名都不一样,从而实现静态资源的同步更新。
- 插件:gulp-rev,gulp-rev-collector
- rev :revision的缩写
- gulp-rev-collector:用于根据文件名的对应关系(gulp-rev生成的manifest.json文件中的对应关系),遍历所有html,替换文件命名。
# 实现效果
<script src="js/main.min.js"></script>
<script src="js/index.min.js"></script>
# 变为
<script src="js/main-c609966787.min.js"></script>
<script src="js/index-1812ef94a5.min.js"></script>
配置md5签名,压缩 ,合并,整合替换的完整流程.
var gulp = require('gulp'),
connect = require('gulp-connect'),
less = require('gulp-less'),
useref = require('gulp-useref'),
uglify = require('gulp-uglify'),
minifyCss = require('gulp-clean-css'),
gulpif = require('gulp-if'),
imagemin = require('gulp-imagemin'),
rev = require('gulp-rev'),
revCollect = require('gulp-rev-collector'),
clean = require('gulp-clean'),
gulpSequence = require('gulp-sequence');
gulp.task('dev', function () {
connect.server({
port: 8060,
})
})
// 文件的清除
gulp.task('clean',function(){
return gulp.src(['./myproject','./.tmp'],{read:false})
.pipe(clean())
})
// css,js的压缩
gulp.task('compress', function () {
return gulp.src('./*.html')
.pipe(useref())
.pipe(gulpif('*.js',uglify()))
.pipe(gulpif('*.css',minifyCss()))
.pipe(gulp.dest('./.tmp'))
})
// 图片压缩
gulp.task('imagemin',function(){
return gulp.src(['./img/*'])
.pipe(imagemin())
.pipe(gulp.dest('./myproject/img'))
})
// css md5签名
gulp.task('css',function(){
return gulp.src('./.tmp/css/*.css')
.pipe(rev()) //给文件加md5签名后缀
.pipe(gulp.dest('./myproject/css')) //签名后输出目录
.pipe(rev.manifest()) //设置md5签名文件的sourcemap
.pipe(gulp.dest('./.tmp/rev/css')) //设置map文件存放目录
})
// js md5签名
gulp.task('js',function(){
return gulp.src('./.tmp/js/*.js')
.pipe(rev())
.pipe(gulp.dest('./myproject/js'))
.pipe(rev.manifest())
.pipe(gulp.dest('./.tmp/rev/js'))
})
// 路径替换
gulp.task('rev',function(){
gulp.src(['./.tmp/rev/**/*.json','./.tmp/*.html'])
.pipe(revCollect())
.pipe(gulp.dest('./myproject'))
})
gulp.task('build',gulpSequence('clean','compress','js','css','rev','imagemin'))
以上的说明:
1. 通过设置.tmp 文件夹用于缓存项目压缩文件,放置md5签名的sourcemap文件,通过rev-collector在.tmp中缓存的manifest.json中对应的文件名关系来替换html中的静态资源引用目录
2. manifest.json : 在使用gulp-rev进行静态资源的md5签名后,通过rev.manifest()生成了签名后资源与html中引用位置的对应关系(即从原index.min.js变为index-1812ef94a5.min.js的引用)