常见方法使用
pipe方法:(gulp中的promise),可以实现顺序调用不同的方法例如:
/**代码功能是对src下的normal.css先压缩后拷贝到dist目录
* 如果是src目录下的所有css就可以写成src('src/*.css')
* **/
const {src,dest}=require("gulp");
const cleanCss=require('gulp-clean-css')
exports.default=()=>{
return src('src/normal.css')
.pipe(cleanCss())
.pipe(dest('dist'))
}
gulp自带方法:
1、src(url,option)
1.url获取资源路径:例如‘src/assets/styles/*.scss’ ----获取src/assets/styles下的所有scss文件,'src/assets/**/*.scss'--获取src/assets目录的所有子目录下的scss文件
2.option:option.base:地址前缀,比如下例在进行拷贝到dist目录时,目标文件相对dist的路径与源文件想对src的路径一致:
3.pipe相当于promise的then将不同操作链接起来
const style=()=>{
return src('src/assets/styles/*.scss',{base:'src'})
.pipe(sass({outputStyle:'expanded'}))
.pipe(dest('dist'))
}
2、dest(url,option):
1.url要拷贝到的目标文件夹的路径
3、parallel(task1,task2…):
1.开启并行任务,task1,task2并行执行
4、series(task1,task2…):
1.开启串行任务,task1,task2按照书写顺序执行
第三方插件
1、gulp-sass(options):
处理样式(sass)文件,options.outputStyle=‘expanded’,展开样式内容
2、gulp-babel(options):
处理js文件,options.presets=[‘@babel/preset-env'],设置js的处理还要安装@babel/core、@babel/preset-env
3、gulp-swig(options):
处理html文件,options.data=data---要向hml注入的数据
4、gulp-imagemin(options):
处理图片文件,可以用来压缩图片和文字(有的文字也是图片--svg)
4、del(options):
可以用来删除上一次生成的dist文件目录下的东西
5、gulp-load-plugins:
例如:const loadPlugins=require('gulp-load-plugins');
const plugins=loadPlugins();那么此时上述对gulp插件的引用可以在文件头部省略直接在使用的地方使用形如plugins.XXX的形式,这样就可以省略在文件头部的require的引用了
构建服务器:
基本构建操作
1.安装插件browser-sync
2.引用:const browserSync=require('browser-sync')
3.获取create方法:const bs=browserSync.create()
4.构建任务:
bs.init({
notify:false,//关闭提示
port:3000,//打开的端口
open:true,//是否打开窗口
files:'dist/**',//监控的路径,当dist中文件或者目录改变时或同步到浏览器中
server:{
baseDir:'dist', //服务器加载的资源目录
routes:{ //优先于baseDir,只有routes里面没有的资源才会去baseDir中寻找
'./node_modules':'node_modules'
}
}
})
本地代理:
gulp可以通过http-proxy-middleware开启反向代理,实现跨域
middleware:function(connect,opt){
return [
proxy("/api",{
target:"https://api.douban.com/",
changeOrigin:true,
pathRewrite:{//路径重写规则
'^/api':''
}
})
]
}
useref文件引用处理
const useref=()=>{
return src("dist/*.html",{base:'dist'}) //处理打包后的构建注释合并一起,包括合并引用的第三方资源(node_modules)
.pipe(plugins.useref({
searchPath:['dist','.']//使用的多的路径在前
}))
.pipe(dest('dist'))
}
代码压缩
1.需要的插件:gulp-htmlmin---压缩html、gulp-uglify---压缩引用的js、gulp-clean-css---压缩引用的css、gulp-if 用来判断资源类型
const useref=()=>{
return src("dist/*.html",{base:'dist'}) //处理打包后的构建注释合并一起,包括合并引用的第三方资源(node_modules)
.pipe(plugins.useref({
searchPath:['dist','.']//使用的多的路径在前
}))
.pipe(plugins.if(/\.js$/,plugins.uglify()))//如果是js则调用压缩js的
.pipe(plugins.if(/\.css$/,plugins.cleanCss()))//如果是css则调用压缩css的
.pipe(plugins.if(/\.html$/,plugins.htmlmin({collapseWhitespace:true,minifyCSS:true,minifyJS:true})))//如果是html则调用压缩html的,collapsewhitespace:true 删除空格;minifyCSS:true:压缩行内样式,minifyJS:true--压缩行内js
.pipe(dest('release'))
}
本地测试配置
const {src,dest,parallel,series,watch}=require("gulp");
const loadPlugins=require('gulp-load-plugins');
const plugins=loadPlugins()
const del=require('del');
const browserSync = require("browser-sync");
const bs=browserSync.create()
const data={name:'hello'};
const clean=()=>{
return del(['dist'])
}
const style=()=>{
return src('src/assets/styles/*.scss',{base:'src'})
.pipe(plugins.sass({outputStyle:'expanded'}))
.pipe(dest('dist'))
.pipe(bs.reload({stream:true}))//测试的时候变化时以stream推送到浏览器
}
const script=()=>{
return src("src/assets/scripts/*.js",{base:'src'})
.pipe(plugins.babel(
{
presets:['@babel/preset-env']
})
)
.pipe(dest('dist'))
.pipe(bs.reload({stream:true}))//测试的时候变化时以stream推送到浏览器
}
const pages=()=>{
return src("src/**/*.html",{base:'src'})
.pipe(plugins.swig({data})
)
.pipe(dest('dist'))
.pipe(bs.reload({stream:true}))//测试的时候变化时以stream推送到浏览器
}
const image=()=>{
return src("src/assets/images/**",{base:'src'})
.pipe(plugins.imagemin())
.pipe(dest('dist'))
}
const fonts=()=>{
return src("src/assets/fonts/**",{base:'src'})
.pipe(plugins.imagemin())
.pipe(dest('dist'))
}
const extra=()=>{
return src("public/**",{base:'public'})
.pipe(dest('dist'))
}
const serve=()=>{
watch('src/assets/styles/*.scss',style)//监控源码scss的变化如果有变化则执行style任务,本操作与上面任务的bs.reload二者取一即可
watch('src/assets/scripts/*.js',script)//监控源码js的变化如果有变化则执行script任务,本操作与上面任务的bs.reload二者取一即可
watch('src/**/*.html',pages)//监控源码html的变化如果有变化则执行pages任务,本操作与上面任务的bs.reload二者取一即可
watch(['src/assets/images/**','src/assets/fonts/**','public/**'],bs.reload) //减少构建在本地开发测试的时候只需要重新加载
// watch('src/assets/images/**',image)//监控源码图片的变化如果有变化则执行image任务
// watch('src/assets/fonts/**',fonts)//监控源码fonts的变化如果有变化则执行fonts任务
// watch('public/**',extra)//监控源码fonts的变化如果有变化则执行extra任务,image,fonts,extra的监控意义不大
bs.init({
server:{
notify:false,//关闭提示
port:3000,//打开的端口
open:true,//是否打开窗口
files:'dist/**',//监控的路径,当dist中文件或者目录改变时或同步到浏览器中
baseDir:['dist','src','public'], //当是数组时按照从前到后的顺序在该目录下查找资源
routes:{ //优先于baseDir,只有routes里面没有的资源才会去baseDir中寻找
'./node_modules':'node_modules'
}
}
})
}
const useref=()=>{
return src("dist/*.html",{base:'dist'}) //处理打包后的构建注释合并一起,包括合并引用的第三方资源(node_modules)
.pipe(plugins.useref({
searchPath:['dist','.']//使用的多的路径在前
}))
.pipe(plugins.if(/\.js$/,plugins.uglify()))//如果是js则调用压缩js的
.pipe(plugins.if(/\.css$/,plugins.cleanCss()))//如果是css则调用压缩css的
.pipe(plugins.if(/\.html$/,plugins.htmlmin({collapseWhitespace:true,minifyCSS:true,minifyJS:true})))//如果是html则调用压缩html的,collapsewhitespace:true 删除空格;minifyCSS:true:压缩行内样式,minifyJS:true--压缩行内js
.pipe(dest('release'))
}
const compile=parallel(style,script,pages,image,fonts)
// 上线之前执行的任务
const build=series(clean,parallel(compile,image,fonts,extra))
const develop=series(clean,compile,serve) //上线的构建任务
module.exports={
build,
develop,
useref
}
打包生产
之前的打包都是本地服务项目,包内没有image等静态资源,而生产则这些资源是必须的,因此需要改动,平时打包可以放到temp中,img,font等不常用的可以直接打包到dist中
const {src,dest,parallel,series,watch}=require("gulp");
const loadPlugins=require('gulp-load-plugins');
const plugins=loadPlugins()
const del=require('del');
const browserSync = require("browser-sync");
const bs=browserSync.create()
const data={name:'hello'};
const clean=()=>{
return del(['dist','temp'])
}
const style=()=>{
return src('src/assets/styles/*.scss',{base:'src'})
.pipe(plugins.sass({outputStyle:'expanded'}))
.pipe(dest('temp'))
.pipe(bs.reload({stream:true}))//测试的时候变化时以stream推送到浏览器
}
const script=()=>{
return src("src/assets/scripts/*.js",{base:'src'})
.pipe(plugins.babel(
{
presets:['@babel/preset-env']
})
)
.pipe(dest('temp'))
.pipe(bs.reload({stream:true}))//测试的时候变化时以stream推送到浏览器
}
const pages=()=>{
return src("src/**/*.html",{base:'src'})
.pipe(plugins.swig({data})
)
.pipe(dest('dist'))
.pipe(bs.reload({stream:true}))//测试的时候变化时以stream推送到浏览器
}
const image=()=>{
return src("src/assets/images/**",{base:'src'})
.pipe(plugins.imagemin())
.pipe(dest('dist'))
}
const fonts=()=>{
return src("src/assets/fonts/**",{base:'src'})
.pipe(plugins.imagemin())
.pipe(dest('dist'))
}
const extra=()=>{
return src("public/**",{base:'public'})
.pipe(dest('dist'))
}
const serve=()=>{
watch('src/assets/styles/*.scss',style)//监控源码scss的变化如果有变化则执行style任务,本操作与上面任务的bs.reload二者取一即可
watch('src/assets/scripts/*.js',script)//监控源码js的变化如果有变化则执行script任务,本操作与上面任务的bs.reload二者取一即可
watch('src/**/*.html',pages)//监控源码html的变化如果有变化则执行pages任务,本操作与上面任务的bs.reload二者取一即可
watch(['src/assets/images/**','src/assets/fonts/**','public/**'],bs.reload) //减少构建在本地开发测试的时候只需要重新加载
// watch('src/assets/images/**',image)//监控源码图片的变化如果有变化则执行image任务
// watch('src/assets/fonts/**',fonts)//监控源码fonts的变化如果有变化则执行fonts任务
// watch('public/**',extra)//监控源码fonts的变化如果有变化则执行extra任务,image,fonts,extra的监控意义不大
bs.init({
server:{
notify:false,//关闭提示
port:3000,//打开的端口
open:true,//是否打开窗口
// files:'dist/**',//监控的路径,当dist中文件或者目录改变时或同步到浏览器中
baseDir:['temp','src','public'], //当是数组时按照从前到后的顺序在该目录下查找资源
routes:{ //优先于baseDir,只有routes里面没有的资源才会去baseDir中寻找
'./node_modules':'node_modules'
}
}
})
}
const useref=()=>{
return src("temp/*.html",{base:'dist'}) //处理打包后的构建注释合并一起,包括合并引用的第三方资源(node_modules)
.pipe(plugins.useref({
searchPath:['dist','.']//使用的多的路径在前
}))
.pipe(plugins.if(/\.js$/,plugins.uglify()))//如果是js则调用压缩js的
.pipe(plugins.if(/\.css$/,plugins.cleanCss()))//如果是css则调用压缩css的
.pipe(plugins.if(/\.html$/,plugins.htmlmin({collapseWhitespace:true,minifyCSS:true,minifyJS:true})))//如果是html则调用压缩html的,collapsewhitespace:true 删除空格;minifyCSS:true:压缩行内样式,minifyJS:true--压缩行内js
.pipe(dest('dist'))
}
const compile=parallel(style,script,pages,image,fonts)
// 上线之前执行的任务
const build=series(clean,parallel(series(compile,useref),image,fonts,extra))//因为compile与useref有先后顺序
const develop=series(compile,serve) //上线的构建任务
module.exports={
build,
develop,
useref
}
封装自动化构建工作流
提取自动化构建流
1.形式:gulp+gulpfile.js=构建工作流
2.gulp CLI+gulpfile=>PAGES
3.步骤:a.创建模块并将其发布到npm上;b.其他项目引用
4.创建模块步骤:a.创建git仓库并在本地初始化仓库
5.提取gulpfile:
a.在某个(XXX)项目或者项目模板中运行yarn link,使得该模板成为全局模板,这样在新文件夹中运行yarn link XXX,即可使用了
b.获取当前工作目录的路径:process.cwd().
6.获取配置文件信息:
//cli的入口类似普通项目的 gulpfils.js与package.json中的bin对应:
module.exports=require('pages');//pages为自定义的脚手架的名称
// 构建项目模板的index.js(gulp配置文件相当于其他项目的gulpfile)
let config={ //default配置
};
try{
const loadConfig=require(path.join(process.cwd(),'/page.config.js'))
config=object.assign({},config,loadConfig)
}catch(e){}
代码改造:
const script=()=>{
return src(config.XX.XX,{base:config.XX.YY})
.pipe(plugins.babel(
{
presets:[require('@babel/preset-env')]
})
)
.pipe(dest(config.XX.zz))
.pipe(bs.reload({stream:true}))//测试的时候变化时以stream推送到浏览器
}
构建cli
1.在bin目录下新建main.js(自定义,一般放到lib文件夹中)
2.在package.json中新增bin属性,值为1中的main.js的全路径
3.在package.json中修改dependencies:值为原脚手架的依赖(即脚手架的dependencies)
4 .新项目的话本地yarn link XXX(制作的cli名称)
5.新项目的gulpfiles.js代码如下:module.exports=require('XXXX')//XXX是上面封装的cli名称
6.main.js的内容:
#!/usr/bin/env node
process.argv.push('--cwd')
process.argv.push(process.cwd())
process.argv.push('--gulpfile')
process.argv.push(require.resolve('..'))
require('gulp/bin/gulp')
7.cli的package.json 中files字段:[‘lib’,‘bin’]