在项目根目录安装gulp
模块
yarn add gulp --dev
npm install --save-dev gulp
根目录下创建gulpfile.js
文件, 作为gulp
配置的入口文件
导入gulp
模块的部分api
:
const { src, dest } = require("gulp");
const sass = require("gulp-sass");
1.style任务:
-
样式编译
-
定义为私有任务,通过
module export
导出具体任务 -
src
创建读取流,dest
创建写入流,dist
用于分发发布 -
这里想通过编译后,与
src
中的目录结构相同,那么需要指定目标路径 -
如果每个任务都手动指定目标路径显然重复臃肿,可以通过在读取流中添加配置项,指定写入流路径
-
saas({ outputStyle: "expanded" })
通配展开样式 -
通过插件转换文件
yarn gulp-sass --dev
安装转换插件并引入
const style = () => {
return src("src/assets/styles/*.scss", { base: "src" })
.pipe(sass({ outputStyle: "expanded" }))
.pipe(dest("dist"))
}
module.exports = {
style
}
通过yarn gulp style
命令运行编译任务。
2.脚本任务:
- 同样定义为私有任务, 通过
module export
导出任务 - 安装插件
yarn add @babel/core @babel/preset-env --dev
, 转换js
- 此时运行报错
- 原因: 这里的
Babel
只是帮你唤起转换进程, 并没有像sass
模块那样真正的转换, 所以需要手动安装@babel/core
模块来实现编译 - 解决办法:
yarn add @babel/core @babel-preset-env --dev
preset
会默认把所有的ECMAScript
代码全部做转换, 并在转换流中添加配置项- 这里如果不指定配置项
{ presets: ["@babel/preset-env"] }
, 那么编译后的文件与源文件没差, 是因为Babel
是ECMAScript
的平台, 具体转换是Babel
内部的插件,preset-env
就是最新的打包集合.
const script = () => {
return src("src/assets/scripts/*.js", { base: "src" })
.pipe(babel({ presets: ["@babel/preset-env"] }))
// .pipe(babel())
.pipe(dest("dist"))
}
通过yarn gulp script
命令运行编译任务。
3.页面模板编译-html文件
- 安装插
yarn add gulp-swig --de
- 通过指
swi
配置项配``htm`中的动态数据 - 由于
html
文件不止在src
下, 也有在其子目录下, 所以这里使用通配符**/*.html
const page = () => {
return src("src/**/*.html", { base: "src" })
// .pipe(swig({ data }))
.pipe(swig())
.pipe(dest("dist"))
}
4.组合任务
通过parallel
方法, 创建组合任务
// 导入parallel模块创建并行任务
const compile = parallel模块(style, script, page)
// 导出
module.exports = {
compile
}
通过yarn gulp compile
命令运行编译任务。执行结果:
5.图片转换
- 安装插件
yarn add gulp-imagemin --dev
- 图片是无损压缩, 只是删除了源数据一些,
svg
格式只是代码格式化处理
/**
* 图片任务
*/
const image = () => {
return src("src/assets/images/**", { base: "src" })
.pipe(imagemin())
.pipe(dest("dist"))
}
通过yarn gulp image
命令运行编译任务。执行结果:
6.文字任务
const font = () => {
return src("src/assets/fonts/**", { base: "src" })
.pipe(imagemin())
.pipe(dest("dist"))
}
添加到组合任务中并导出:
// 组合任务
const compile = parallel(style, script, page, image, font)
// 导出模块
module.exports = {
compile
}
7.其他文件
/**
* 其他任务
*/
const extra = () => {
return src("public/**", { base: "public" })
.pipe(dest("dist"))
}
compile
任务构建src
项目中的需要编译的文件,为了不混淆,这里重新创建一个任务
const compile = parallel(style, script, page, image, font)
const build = parallel(compile, extra);
// 导出模块
module.exports = {
build
}
8.文件清除
- 安装插件:
yarn add del --dev
del
模块返回promise
对象, 可以支持clean
方法标记完成del
模块不属于gulp
- 清除任务执行在编译之前, 先清除后编译, 不能使用并行, 导入
serice
串行执行。
const { src, dest, parallel, series } = require("gulp");
const del = require("del");
// 定义清除任务
const clean = () => {
return del(["dist"])
}
const build = series(clean, parallel(compile, extra));
通过yarn gulp build
命令运行编译任务。执行结果:
8.自动加载插件
- 随着编译任务越来越多, 手动加载插件就变得繁重, 这里采用一个插件加载.
- 安装插件:
yarn add gulp-load-plugins --dev
plugins
是一个对象, 所有插件会成为这个对象上的属性- 将所有插件重命名为
plugins.{name}
的形式
const loadPlugins = require("gulp-load-plugins");
const plugins = loadPlugins();
// const plugins.sass = require("gulp-sass");
// const plugins.babel = require("gulp-babel");
// const plugins.swig = require("gulp-swig");
// const plugins.imagemin = require("gulp-imagemin");
9.热更新开发服务器
- 开发调试应用, 实现代码更改后自动编译, 自动刷新浏览器页面
- 安装模块:
yarn add browser-sync --dev
browser-sync
模块支持代码更改后热更新到浏览器- 并不是
gulp
插件, 提供create
方法自动创建开发服务器 baseDir
方法指定运行到浏览器的路径, 这里指定编译后的dist
// 导入插件
const loadPlugins = require("gulp-load-plugins");
// 创建开发服务器
const bs = browserSync.create();
// 初始化并启动
const serve = () => {
bs.init({
server: {
baseDir: "dist"
}
})
}
此时启动后, 会没有加载node_modules
下的一些资源拷贝, 所以页面并没有加载全部,
通过给bs
模块配置路由指向本地目录的node_modules
, 如果routes
有配置会先执行, 然后再执行baseDir
中的路径.
// 单独定义开发服务器启动
const serve = () => {
bs.init({
notify: false, // 启动时不弹出提示
port: 2080, // 端口
// open: false,
server: {
baseDir: "dist",
routes: {
"/node_modules": "node_modules"
}
}
})
}
此时加入热更新, 执行顺序应该是先clean
清除后, 执行build
编译源代码到dist
目录, 编译完成后再执行serve
更新到浏览器页面, 这里暂不考虑源代码变更后执行, 先加入dist
目录下文件变化后更新.
加入files
指定路径, 这里就是dist
下的所有文件.
const serve = () => {
bs.init({
notify: false, // 启动时不弹出提示
port: 2080, // 端口
// open: false,
files: "dist/**",
server: {
baseDir: "dist",
routes: {
"/node_modules": "node_modules"
}
}
})
}
通过yarn gulp serve
启动服务, 修改dist
下任意文件可观察到已生效.
10.监视变化以及构建优化
- 借助
gulp
中的watch
方法监听. 此方法第一个参数接收通配符, 第二个参数即执行函数, 在serve
启动的时候监听文件变化. - 此时在启动
serve
的时候, 就会先执行watch
的监听, 一旦发现有变化, 执行对应的编译任务, 编译完后启动服务器, 那么此时久完成了之前src
变化后, 同步到浏览器页面.
如下:
// 导入watch方法
const { src, dest, parallel, series, watch } = require("gulp");
const serve = () => {
watch("src/assets/styles/*.scss", style)
watch("src/assets/styles/*.js", script)
watch("src/**/*.html", page)
watch("src/assets/images/**", image)
watch("src/assets/fonts/**", font)
watch("public/**", extra)
bs.init({
notify: false, // 启动时不弹出提示
port: 2080, // 端口
// open: false,
files: "dist/**",
server: {
baseDir: "dist",
routes: {
"/node_modules": "node_modules"
}
}
})
}
那么这里还存在两个问题:
- 上面的图片, 字体以及
public
目录下的文件只是做了拷贝, 并不会影响源文件, 所以这些文件只需在上线之前进行编译压缩即可, 所以开发阶段忽略这些文件的编译.如下:serve
中的watch
方法不再监听图片文字等,baseDir
改为数组, 会按照顺序依次向后查询. - 如果是首次编译, 直接执行
serve
, 那么此时dist
文件还没有生成, 那么就找不到对应路径, 报错, 所以这里将serve
任务和build
组合, 编译生成dist
目录后再启动web
服务器, 串行执行. - 也希望上面三类文件变化后自动更新浏览器, 可使用
watch[]
的形式
// 单独定义开发服务器启动
const serve = () => {
watch("src/assets/styles/*.scss", style)
watch("src/assets/styles/*.js", script)
watch("src/**/*.html", page)
// watch("src/assets/images/**", image)
// watch("src/assets/fonts/**", font)
// watch("public/**", extra)
watch([
"src/assets/images/**",
"src/assets/fonts/**",
"public/**"
], bs.reload)
bs.init({
notify: false, // 启动时不弹出提示
port: 2080, // 端口
// open: false,
files: "dist/**",
server: {
baseDir: ["dist", "src", "public"],
routes: {
"/node_modules": "node_modules"
}
}
})
}
组合任务, 开发模式下, 编译后在执行serve
:
const compile = parallel(style, script, page)
const build = series(clean, parallel(compile, extra, image, font));
const develop = series(compile, serve)
// 导出模块
module.exports = {
clean,
compile,
build,
serve,
develop
}
通过yarn gulp develop
命令运行编译任务。执行结果:
11.useref文件引入处理
node_modules/
下的文件引入, 之前的处理是指向本地的开发文件, 上线后dist
并没有这些文件- 安装插件:
yarn add gulp-useref --dev
- 原理: 这个插件会根据
dist
目录下的标识将这些引入的文件编译到一个新的文件.如图
const useref = () => {
return src("dist/*.html", { base: "dist" })
.pipe(plugins.useref({ searchPath: ["dist", "."] }))
.pipe(dest("dist"))
}
通过yarn gulp useref
命令运行编译任务。执行后的目录结构:
12.文件压缩
- 安装插件:
yarn add gulp-htmlmin gulp-uglify gulp-clean-css --dev
- 同时需要判断是哪类文件, 执行哪类的压缩安装
if
插件:yarn add gulp-if --dev
此时存在一个问题:
dist
目录同时进行读写操作, 会造成文件冲突, 有的文件不能写入, 所以这时需要指定临时目录temp
, 在编译完后, 进行useref
对引入的文件进行处理, 最后写入到dist
目录.
那么此时的gulpfile.js
如下:
// 实现这个项目的构建任务
/**
* 导入gulp模块的部分api
*/
const { src, dest, parallel, series, watch } = require("gulp");
const del = require("del");
const browserSync = require("browser-sync")
const loadPlugins = require("gulp-load-plugins");
const plugins = loadPlugins();
const bs = browserSync.create();
// 定义清除任务
const clean = () => {
return del(["dist", "temp"])
}
/**
* 样式编译
* 定义为私有任务,通过module export 导出具体任务
* src 创建读取流 dest创建写入流 dist用于分发发布
* 这里想通过编译后,与src中的目录结构相同,那么需要指定目标路径
* 如果每个任务都手动指定目标路径显然重复臃肿,可以通过在读取流中添加配置项,指定写入流路径
* 通过插件转换文件yarn gulp-sass --dev 安装转换插件并引入
*/
const style = () => {
return src("src/assets/styles/*.scss", { base: "src" })
.pipe(plugins.sass({ outputStyle: "expanded" }))
.pipe(dest("temp"))
.pipe(bs.reload({ stream: true })) // 以流的形式推到浏览器, serve就不需要files参数了
}
/**
* 脚本任务
* base拷贝的基本目录
* 安装插件yarn add @babel/core @babel/preset-env --dev, 转换js
*/
const script = () => {
return src("src/assets/scripts/*.js", { base: "src" })
.pipe(plugins.babel({ presets: ['@babel/preset-env'] }))
// .pipe(babel())
.pipe(dest("temp"))
.pipe(bs.reload({ stream: true }))
}
/**
* 页面编译任务
* 通过指定swig配置项配置html中的动态数据
*/
const page = () => {
return src("src/**/*.html", { base: "src" })
// .pipe(swig({ data }))
.pipe(plugins.swig())
.pipe(dest("temp"))
.pipe(bs.reload({ stream: true }))
}
/**
* 图片任务
*/
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/styles/*.js", script)
watch("src/**/*.html", page)
// watch("src/assets/images/**", image)
// watch("src/assets/fonts/**", font)
// watch("public/**", extra)
watch([
"src/assets/images/**",
"src/assets/fonts/**",
"public/**"
], bs.reload)
bs.init({
notify: false, // 启动时不弹出提示
port: 2080, // 端口
// open: false,
// files: "dist/**",
server: {
baseDir: ["temp", "src", "public"],
routes: {
"/node_modules": "node_modules"
}
}
})
}
// 引入文件的处理
const useref = () => {
return src("temp/*.html", { base: "temp" })
.pipe(plugins.useref({ searchPath: ["temp", "."] }))
.pipe(plugins.if(/\.js$/, plugins.uglify()))
.pipe(plugins.if(/\.css$/, plugins.cleanCss()))
.pipe(plugins.if(/\.html$/, plugins.htmlmin({
collapseWhitespace: true,
minifiCss: true,
minifiJs: true
})))
.pipe(dest("dist"))
}
// 组合任务
const compile = parallel(style, script, page)
/**
* compile任务构建src项目中的需要编译的文件,为了不混淆,这里重新创建一个任务
* 清除任务执行在编译之前,先清除后编译,不能使用并行。
*/
const build = series(
clean,
parallel(
series(compile, useref),
extra,
image,
font
)
);
const develop = series(compile, serve)
// 导出模块
module.exports = {
clean,
compile,
build,
serve,
develop,
useref
}
13.补充
在package.json
文件中, 加入上面的任务命令, 更方便的使用
"scripts": {
"clean": "gulp clean",
"lint": "gulp lint",
"serve": "gulp serve",
"build": "gulp build",
"start": "gulp start",
"deploy": "gulp deploy --production"
},
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!