项目目录结构如下
gulp-demo
├─ .gitignore
├─ gulpfile.js
├─ LICENSE
├─ package.json
├─ public
│ └─ favicon.ico
├─ README.md
└─ src
├─ about.html
├─ assets
│ ├─ fonts
│ │ ├─ pages.eot
│ │ ├─ pages.svg
│ │ ├─ pages.ttf
│ │ └─ pages.woff
│ ├─ images
│ │ ├─ brands.svg
│ │ └─ logo.png
│ ├─ scripts
│ │ └─ main.js
│ └─ styles
│ ├─ demo.scss
│ ├─ main.scss
│ ├─ _icons.scss
│ └─ _variables.scss
├─ features.html
├─ index.html
├─ layouts
│ └─ basic.html
└─ partials
├─ footer.html
├─ header.html
└─ tags.html
● 样式编译
○ 安装gulp
○ 在入口文件中配置:
const {src,dest} = require("gulp")
// yarn add gulp-sass sass --dev
const sass = require("gulp-sass")(require('sass'))
const style = ()=>{
//读入样式文件,base:src表示写入的文件保留src之后的文件层级
return src('src/assets/styles/*.scss',{base:'src'})
//将sass文件转换,且样式的括号打开
.pipe(sass({outputStyle:'expanded'}))
.pipe(dest('dist'))
}
module.exports = {
style
}
● 脚本编译
○ 将es6编译成es5
const {src,dest} = require("gulp")
//yarn add gulp-babel
//yarn add @babel/core @babel/preset-env --dev
const babel = require("gulp-babel")
// yarn add gulp-sass sass --dev
const sass = require("gulp-sass")(require('sass'))
const style = ()=>{
//读入样式文件,base:src表示写入的文件保留src之后的文件层级
return src('src/assets/styles/*.scss',{base:'src'})
//将sass文件转换,且样式的括号打开
.pipe(sass({outputStyle:'expanded'}))
.pipe(dest('dist'))
}
const script = ()=>{
return src("src/assets/scripts/*.js",{base:'src'})
.pipe(babel({presets:['@babel/preset-env']}))
.pipe(dest('dist'))
}
module.exports = {
style,
script
}
● 模板文件编译
○ 将模板html文件渲染编译
○ 安装渲染模块yarn add gulp-swig
const page = ()=>{
return src("src/**/*.html",{base:'src'})
//渲染模板,传入数据
.pipe(swig({data}))
.pipe(dest('dist'))
}
● 对字体和图片的压缩
○ 安装插件:yarn add gulp-imagemin --dev
■ 版本太高可能报错:https://blog.csdn.net/qq_25972233/article/details/123045152
const image = ()=>{
return src("src/assets/images/**",{base:'src'})
.pipe(imagemin())
.pipe(dest('dist'))
}
const font = ()=>{
return src("src/assets/fonts/**",{base:'src'})
.pipe(imagemin())
.pipe(dest('dist'))
}
● 处理完src目录下的文件还需要处理public下的文件,这里的文件属于直接调用的文件,之间复制到dist目录中即可
const extra = ()=>{
return src("public/**",{base:'public'})
.pipe(dest("dist"))
}
const compile = parallel(style,script,page,image,font)
const bulid = parallel(compile,extra)
○ 通过build可以把文件全部打包到dist目录,但是每一次build前需要把之前的dist删除再重新生成,这里就需要一个删除文件夹的命令
○ 安装模块:yarn add del --dev
const del = ()=>{
return del(['dist'])
}
const bulid = series(del,parallel(compile,extra))
● 自动加载插件
○ 随着插件越来越多,每一次引用导致代码太长不易维护
○ 使用模块:yarn add gulp-load-plugins --dev可以自动加载所有插件
const plugins = loadPlugins()
○ 删除gulp插件的引用,以后用到插件只需plugins.插件名
● 创建服务器热更新
○ 安装:yarn add browser-sync --dev
○ 引入模块之后,创建热更新任务
const serve = ()=>{
//bs为安装的模块
bs.init({
notify:false,//是否提示
port:2080,
//监听的文件,文件改变,浏览器刷新
files:'dist/**',
server:{
//指定网站根目录
baseDir:'dist',
routes:{
//dist中html文件引入node_modules中的模块,这里告诉浏览器如果html中有/node_modules,就直接去根目录下的node_modules中找,后面会将node_modules中需要的文件提取到dist中
'/node_modules':'node_modules'
}
}
})
}
○ serve中配置的是对打包好的dist下的监听,在实际上线前,如何对开发环境进行监听呢?
■ 可以借助gulp中的watch模块
■ 在serve运行的时候,监听src目录下的变化,同时调用之前的任务打包对应的变化
■ 值得注意的是,我们通常会监听js、css等文件变化,而图片字体的变化一般监听的时候不会让它进行打包,因为很耗费性能,只在最后上线的时候才打包,那么如何保证dist目录中存在这个字体和样式以便被网站显示呢?
■ 其实既然不打包,dist中就不必出现这些文件,只需要修改serve中的baseDir监听,对src或public下的文件也进行搜索,当dist中的文件引用不存在,会依次向src搜索
const serve = ()=>{
//监听
watch('src/assets/styles/*.scss',style)
watch("src/assets/scripts/*.js",script)
watch("src/**/*.html",page)
//下面的资源文件监听,服务器执行刷新命令即可
watch([
"src/assets/images/**",
"src/assets/fonts/**",
"public/**"
],bs.reload)
bs.init({
notify:false,//是否提示
port:2080,
//监听的文件,文件改变,浏览器刷新
files:'dist/**',
server:{
//指定网站根目录
baseDir:['dist','src','public'],
routes:{
//dist中html文件引入node_modules中的模块,这里告诉浏览器如果html中有/node_modules,就直接去根目录下的node_modules中找,后面会将node_modules中需要的文件提取到dist中
'/node_modules':'node_modules'
}
}
})
}
● useref文件引用处理
○ html中link标签引入很多css文件,这些文件的路径有的是开发者规定好的,有的则在node_modules下
○ 可以使用gulp-useref来提取这些文件,并将它们合并到一起
const useref = ()=>{
return src("dist/*.html",{base:'dist'})
//搜索的位置,本项目css文件,一般在dist,node_modules中
.pipe(plugins.useref({ searchPath:['dist','.'] }))
.pipe(dest('dist'))
}
● 文件资源压缩
○ 打包之后我们发现html、css、js没有压缩
○ yarn add gulp-htmlmin gulp-uglify gulp-clean-css --dev 分别安装html js css压缩模块
○ 我们将插件放在useref任务中,当扫描html文件时,就可以对引用的文件进行压缩
○ 在扫描时,需要对文件类型进行判断,安装yarn add gulp-if插件实现
const useref = ()=>{
return src("dist/*.html",{base:'dist'})
//搜索的位置,本项目css文件,一般在dist,node_modules中
.pipe(plugins.useref({ searchPath:['dist','.'] }))
//判断是否.js结尾文件并压缩
.pipe(plugins.if(/\.js$/,plugins.uglify()))
.pipe(plugins.if(/\.css$/,plugins.cleanCss()))
.pipe(plugins.if(/\.html$/,plugins.htmlmin({
collapseWhitespace:true, //压缩空格
minifyCSS:true,//压缩行内样式
minifyJS:true //压缩内部js
})))
.pipe(dest('release'))
}
● 重新规划构建流程
○ 可以看到,我们之前打包到dist目录的文件只是中间文件,最后要经过useref压缩之后才是最后的文件,如果想要最后文件为dist,就需要规划一个临时文件夹存放打包的文件,然后最后压缩到dist目录中
const {src,dest,parallel,series,watch} = require("gulp")
const loadPlugins = require("gulp-load-plugins")
const sass = require("gulp-sass")(require("sass"))
const del = require("del")
const bs = require("browser-sync")
const plugins = loadPlugins()
const clean = ()=>{
return del(['dist','temp'])
}
const style = ()=>{
//读入样式文件,base:src表示写入的文件保留src之后的文件层级
return src('src/assets/styles/*.scss',{base:'src'})
//将sass文件转换,且样式的括号打开
.pipe(sass({outputStyle:'expanded'}))
.pipe(dest('temp'))
}
const script = ()=>{
return src("src/assets/scripts/*.js",{base:'src'})
.pipe(plugins.babel({presets:['@babel/preset-env']}))
.pipe(dest('temp'))
}
const data = {
menus: [
{
name: 'Home',
icon: 'aperture',
link: 'index.html'
},
{
name: 'Features',
link: 'features.html'
},
{
name: 'About',
link: 'about.html'
},
{
name: 'Contact',
link: '#',
children: [
{
name: 'Twitter',
link: 'https://twitter.com/w_zce'
},
{
name: 'About',
link: 'https://weibo.com/zceme'
},
{
name: 'divider'
},
{
name: 'About',
link: 'https://github.com/zce'
}
]
}
],
pkg: require('./package.json'),
date: new Date()
}
const page = ()=>{
return src("src/**/*.html",{base:'src'})
//渲染模板,传入数据
.pipe(plugins.swig({data}))
.pipe(dest('temp'))
}
const image = ()=>{
return src("src/assets/images/**",{base:'src'})
.pipe(plugins.imagemin())
.pipe(dest('dist'))
}
const font = ()=>{
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)
watch("src/assets/scripts/*.js",script)
watch("src/**/*.html",page)
//下面的资源文件监听,服务器执行刷新命令即可
watch([
"src/assets/images/**",
"src/assets/fonts/**",
"public/**"
],bs.reload)
bs.init({
notify:false,//是否提示
port:2080,
//监听的文件,文件改变,浏览器刷新
files:'dist/**',
server:{
//指定网站根目录
baseDir:['temp','src','public'],
routes:{
//dist中html文件引入node_modules中的模块,这里告诉浏览器如果html中有/node_modules,就直接去根目录下的node_modules中找,后面会将node_modules中需要的文件提取到dist中
'/node_modules':'node_modules'
}
}
})
}
const useref = ()=>{
return src("temp/*.html",{base:'temp'})
//搜索的位置,本项目css文件,一般在dist,node_modules中
.pipe(plugins.useref({ searchPath:['temp','.'] }))
//判断是否.js结尾文件并压缩
.pipe(plugins.if(/\.js$/,plugins.uglify()))
.pipe(plugins.if(/\.css$/,plugins.cleanCss()))
.pipe(plugins.if(/\.html$/,plugins.htmlmin({
collapseWhitespace:true, //压缩空格
minifyCSS:true,//压缩行内样式
minifyJS:true //压缩内部js
})))
.pipe(dest('dist'))
}
const compile = parallel(style,script,page)
const build = series(clean,parallel( series(compile,useref), extra,image,font))
const develop = series(compile,serve)
module.exports = {
compile,
build,
serve,
develop,
useref
}