前言
“用自动化构建工具增强你的工作流程!”,如官网标语所说,gulp 是基于流(stream)的自动化构建工具。
一、gulp的基本知识
首先:
1.需要运行一下yarn init -y 初始化一下package.json文件;
2. 装一下需要使用的依赖项:(可以自己选版本,但是新版可能用法会不一样)
yarn add gulp@4.0.2 gulp-clean-css@4.3.0 gulp-rename@2.0.0 --dev
3.然后新建如图文件结构:
注:src下的css随便写点样式(尽量多写点,写点注释之类的),
准备工作就做完了
1. 简单使用(写一个简单的任务)
(1)书写格式推荐
- 不推荐写法:
//gulpfile.js文件
const gulp = require("gulp");
gulp.task("foo", done => {
console.log("foo task working~");
done()
})
注:调用gulp.task是旧版本,目前能正常运行,只是不推荐(怕以后不支持);
- 推荐写法
//gulpfile.js文件
exports.foo = done => {
console.log("foo task working~");
done()
}
运行命令很简单,在控制台输入 yarn gulp foo;
注意:gulp4.0版本后就取消了同步处理机制,所有任务都是异步处理了,所以需要用一个回调函数来告诉gulp任务已结束,如图done(参数名不强制)这个函数回调,不会不调用done的结果就是:(但是输出语句是正常执行了)
(2)用法示例
//gulpfile.js文件
exports.foo = done => {
console.log("foo task working~");
done()
}
控制台输入 yarn gulp foo
//gulpfile.js文件
exports.default = done => {
console.log("default task working~");
done()
}
控制台输入 yarn gulp(可以省略任务名)
2. gulp组合任务
gulp提供了两个api:series(串行), parallel(并行),这两个api给我们提供了任务之间的组合操作;
//gulpfile.js文件
const { series, parallel } = require("gulp")
const task1 = done => {
setTimeout(() => {
console.log("task1 working~");
done();
}, 1000);
}
const task2 = done => {
setTimeout(() => {
console.log("task2 working~");
done();
}, 1000);
}
const task3 = done => {
setTimeout(() => {
console.log("task3 working~");
done();
}, 1000);
}
exports.foo = series(task1, task2, task3);
exports.bar = parallel(task1, task2, task3);
如上图,分别有task1,task2,task3三个setimeout的延迟任务,我们使用series, parallel组合成两个新任务foo、bar,foo任务是串行的方式执行这三个任务,bar任务是并行的执行这三个任务;
执行foo任务:yarn gulp foo
执行bar任务:yarn gulp bar
3. gulp异步任务处理方式
前面我们说过,gulp的任务都是异步任务(4.0版本以后去掉了同步任务),而异步任务是没办法告诉gulp该任务是否已结束,只能任务内部通过回调方法或者事件的方式通知gulp该任务已结束;
下面我们来介绍三种异步任务处理方式:
(1)调用回调的方式
//gulpfile.js文件
exports.callback = done => {
console.log("callback task~");
done();
}
//gulpfile.js文件
//跟node一样,错误优先的思想
exports.callback_err = done => {
console.log("callback task~");
done(new Error("task failed~"))
}
(2)promise / async await的方式
- promise方式
//gulpfile.js文件
exports.promise = () => {
console.log("promise task~");
return Promise.resolve()//传值会被gulp忽略
}
exports.promise_err = () => {
console.log("promise task~");
return Promise.reject(new Error("task failed~"))
}
- async await方式(需要node8以上)
//gulpfile.js文件
const timeout = (time) => {
return new Promise(resolve => {
setTimeout(resolve, time);
})
}
exports.async = async () => {
await timeout(2000);
console.log("async task~");
}
(3)stream的方式(大部分都是这种处理方式,stream中会有end的事件,该事件会触发任务的结束)
//gulpfile.js文件
const fs = require("fs");
exports.stream = () => {
const readStream = fs.createReadStream("package.json");
const writeStream = fs.createWriteStream("temp.txt");
readStream.pipe(writeStream);
//触发读操作的end事件
return readStream;
}
//还原end事件的结束操作
exports.stream_end = (done) => {
const readStream = fs.createReadStream("package.json");
const writeStream = fs.createWriteStream("temp.txt");
readStream.pipe(writeStream);
readStream.on("end", () => {
done()
})
}
4. gulp构建核心工作原理
构建任务具体要做的事情,也就是所谓的构建过程,原理如图:
具体请看代码:
//gulpfile.js文件
const fs = require("fs");
const { Transform } = require("stream")
exports.default = () => {
const read = fs.createReadStream("src/normalize.css");
const write = fs.createWriteStream("normalize.min.css");
const transform = new Transform({
transform: (chunk, encoding, callback) => {
//核心转换过程实现
//chunk =》读取流中读取到的内容(Buffer)
const input = chunk.toString();
const output = input.replace(/\s+/g, "").replace(/\/\*.+?\*\//g, "");
callback(null, output);
}
})
//把读出来文件流导入到写文件流
read
.pipe(transform)//转换
.pipe(write)//写入
return read;
}
5. gulp的api使用
//gulpfile.js文件
const { src, dest } = require("gulp");
const cleanCss = require("gulp-clean-css");
const rename = require("gulp-rename");
exports.default = () => {
return src("src/*.css")
.pipe(cleanCss())
.pipe(rename({ extname: '.min.css' }))
.pipe(dest("dest"));
}
利用gulp提供src方法读取文件变成流,再通过dest方法把流写入到另一个文件里,中间我们可以加各种操作,比如压缩、更改扩展名等;
二、gulp的demo实践(主要是书写gulpfile.js文件)
新构建一个基础文件目录结构:
github原始代码库地址=》https://github.com/usefire/gulp-demo
git地址:https://github.com/usefire/gulp-demo.git
目录结构:
1.工作流
(1)基本工作流
第一步:yarn install装一下插件
第二步:在gulpfile.js文件写上各种任务
//gulpfile.js文件
const { src, dest, parallel, series, watch } = require("gulp")
const del = require("del")
/**自动加载插件 */
const loadPlugins = require("gulp-load-plugins")
const plugins = loadPlugins()
const sass = require("gulp-sass")(require("sass"))//因为新版本不内置sass,这里就手动版吧
// const babel = require("gulp-babel")
// const swig = require("gulp-swig")
// const imagemin = require("gulp-imagemin")
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 clean = () => {
return del(['temp'])
}
const style = () => {
return src("src/assets/styles/*.scss", { base: "src" })
.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 page = () => {
return src("src/**/*.html", { base: 'src' })
.pipe(plugins.swig({ data, defaults: { cache: false } }))
.pipe(dest("temp"))
}
const compile = series(clean, parallel(style, script, page))
module.exports = {
clean,
compile
}
其中gulp-load-plugins插件得作用是自动加载package.json文件中的Gulp插件(简化require引入),用parallel和series方法组成一个先清空temp文件再并发执行sass、js、html编译任务的compile组合任务,我们只要再命令行执行yarn gulp compile 就能得到编译后的文件。
(2)加上热更新、统一处理html中资源地址和代码压缩功能
1.加上browser-sync插件,开启一个服务,再配置相关的属性来达到热更新的目的,具体更多配置请看browser-sync文档;
2.使用gulp-useref插件,将HTML引用的多个CSS和JS合并起来,减小依赖的文件个数,从而减少浏览器发起的请求次数
3.使用gulp-if插件,对gulp-useref插件读取出来的文件做分流,对不同文件做不同的操作,比如压缩等
gulp-useref和gulp-if更多配置和用法,请查阅相关文档
const { src, dest, parallel, series, watch } = require("gulp")
const del = require("del")
const loadPlugins = require("gulp-load-plugins")
const plugins = loadPlugins()
/**2.自动加载插件 */
const sass = require("gulp-sass")(require("sass"))//因为新版本不内置sass,这里就手动版吧
// const babel = require("gulp-babel")
// const swig = require("gulp-swig")
// const imagemin = require("gulp-imagemin")
/**3.启动小服务 */
const browserSync = require("browser-sync")
const bs = browserSync.create();
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 clean = () => {
return del(['dist', 'temp'])
}
const style = () => {
return src("src/assets/styles/*.scss", { base: "src" })
.pipe(sass({ outputStyle: 'expanded' }))
.pipe(dest("temp"))
.pipe(bs.reload({ stream: true }))
}
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 }))
}
const page = () => {
return src("src/**/*.html", { base: 'src' })
.pipe(plugins.swig({ data, defaults: { cache: false } }))
.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 useref = () => {
return src("temp/*.html", { base: 'temp' })
.pipe(plugins.useref({ searchPath: ['temp', '.'] }))
//读取了html中所有引入的css,js的引入路径文件(包含本地和第三方)
//这里读出了html,css,js三种格式文件,需要使用压缩插件gulp-htmlmin,gulp-uglify,gulp-clean-css,使用gulp-if判断文件流类型
.pipe(plugins.if(/\.js$/, plugins.uglify()))
.pipe(plugins.if(/\.css$/, plugins.cleanCss()))
.pipe(plugins.if(/\.html$/, plugins.htmlmin({
collapseWhitespace: true,
minifyCSS: true,
minifyJS: true
})))
// .pipe(dest('dist')) //会有读写混乱的问题
.pipe(dest("dist"))
}
const server = () => {
watch('src/assets/styles/*.scss', style)
watch("src/assets/scripts/*.js", script)
watch("src/**/*.html", page)
//dev环境,不监听这些文件,因为只涉及到搬运文件和压缩,无编译
// 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: 4090,
// files: 'dist/**',//当不使用这个监听方式时,需要在对应的任务的pipe里加上.pipe(bs.reload({ stream: true })),如上的style和js,html
server: {
//开发环境可以匹配"src", "public"下的字体或者图片
baseDir: ["temp", "src", "public"],
routes: {
//优先级最高
"/node_modules": "node_modules"
}
}
})
}
const compile = parallel(style, script, page)
//转义-》搬运和压缩图片和字体-》压缩html、js、css
const build = series(
clean,
parallel(
series(compile, useref),
image,
font,
extra
))
//dev环境不做图片和字体等的搬运和压缩,只进行转换(js、scss等)
const develop = series(compile, server)
module.exports = {
clean,
build,
develop
}
(1)开发环境(develop)
1.如图二,需要对browser-sync这个小型服务做一定的配置,设置端口为4090,配置服务取加载资源时寻找的文件目录(routes优先级高于baseDir),比如图一中bootstrap.css文件是在node_modules目录中,还有字体图片等;
2.如图二,利用gulp中的watch方法监听js、css、html文件,当文件变更就执行对应的任务;
3.如图二,图片和字体等在开发调试阶段,只要监听当他们发生变化,刷新一下浏览器就好,不用做其他处理,这里需要使用到这个服务reload api;
4.如图二,正常来说,我们需要配置服务的files属性,用于当对应文件变更就刷新浏览器,但是我们可以用另一种方式来实现这种监听;其中watch方法已经监听当文件发生变化,执行了对应的编译任务,那我们为啥不在它编译完后就通知浏览器刷新呢,所以如图三,在每个任务后面加上reload方法就行;
图一
图二
图三
4.运行命令 yarn gulp develop,该任务只对js、css、html做编译处理,图片和字体等不需要做处理,地址端口就是我们在bs.init里配置的端口,
(2)生产编译
在开发环境,因为是本地调试,所以我们可以不对bootstrap.css或者图片等资源路径做处理没啥问题,只要在本地服务里配置号映射就好了,但是当发到远程服务上去,这些资源就会丢失找不到了,那怎么办呢?请看下面分解
- (如图一)需要用到一个插件gulp-useref,它解析html中引入的js和css资源,并根据注释(html编译时会给js、css的引入链接加上注释,具体请看编出的html文件的代码)合并js和css,生成新的文件并修改引入链接地址;
- (如图一)使用gulp-if插件来分类流,并对他们做不同的压缩操作等其他操作,最后都把他们写道dist目录中
- ( 如图二)通过任务把字体、图片和公共文件搬运到dist目录下
- 最后把这些任务组合成build任务,运至yarn gulp build打包成dist,然后使用dist发布到服务就行
图一
图二
图三
三、工作流封装
1.本地调试
当我们很多项目都需要同一份工作流配置时:
第一种方式:我们可以复制gulpfile.js到不同目录下,并创建指定的目录结构,这样没问题,只是不方便维护,比如你想修改某个配置,则需要多个项目同时修改,所以pass;
第二种方式就是打包成一个npm包,哪个项目想使用只要引入一下就好了,修改配置时,只要改个npm包再发布就好了,这个方法可行;
项目目录结构
- 运行新建一个名为yw-gulpfile文件夹,在yw-gulpfile文件夹下运行命令
yarn init -y
,生成一个package.json文件; - 根目录新建lib/index.js
- package.json相关说明:插件里的package.json,里面的字段配置与npm发布息息相关。
name npm包名
version npm包版本号,版本号是很有讲究的,一般用0.0.0形式分为三部分。第一部分用于不兼容更新,第二部分用于功能新增,第三部分用于bug修复。
description npm包的描述
main 引用npm包的入口文件
keywords npm官方仓库搜索时的关键词
license 开源协议类型,对应LICENSE文件。
files npm上传文件白名单,有些文件是默认会上传的,例如LICENSE、package.json、README.md。(.npmignore文件配置的是黑名单)
repository 源码仓库地址
homepage 插件官网,没有时默认取repository的地址
dependencies dependencies定义插件在生产环境所依赖的包,外部项目安装该插件时也会自动安装插件dependencies里的包(如果外部项目已安装过这些依赖就不再重复安装了),所以注意区分插件的dependencies和devDependencies
peerDependencies 插件本身可能依赖一些其他包(即上述dependencies定义的包),且对依赖包有版本要求,就可以用peerDependencies来指定这些依赖的版本范围,如果外部项目在安装当前插件前已经安装过这些依赖,但不符合版本范围,在安装当前插件时就会有警告提示。
typings ts类型声明文件的路径
bin 用于配置命令脚本,我这里组件插件用不到,如果你的插件是node命令,就用这个配置命令名及对应的可执行脚本文件路径。npm在安装插件时会自动在node_modules/.bin目录创建指向你插件脚本的链接。
sideEffects 用于tree shaking优化,默认为true,设置为false或一个数组(排除列表)可以让插件支持tree shaking,不清楚的请慎用。
- 修改package.json里的main为lib/index.js,然后把
gulp-demo
项目里的gulpfile.js文件里代码剪切到lib/index.js文件里,再把gulp-demo
项目package.json里的devDependencies依赖都复制到yw-gulpfile项目的package.json里的dependencies依赖里(因为是yw-gulpfile项目发布了以后用的依赖),yw-gulpfile项目运行yarn install
,最后运行yarn link
(用于调试)。 - 回到
gulp-demo
项目,运行yarn link yw-gulpfile
,node_module就能找到这个包了,然后需要在gulpfile.js里写上module.exports = require("yw-gulpfile")
,运行yarn gulp build
,会报:gulp找不到,这个问题发到npm包以后就不会有了,先临时装一下:yarn add gulp gulp-cli --dev
; 再次运行yarn gulp build
,会报错:读不到package.json,这是因为之前gulpfile.js里我们读取了这个文件,且data数据是写死的,所以我们要把data数据变成可配置的; - 把lib/index.js里的各种路径和参数变成可配置的:
gulp-demo
根目录新建一个page.config.js文件,把data数据复制过去,然后在lib/index.js读取该文件就好了,然后data数据使用读取过来的data数据就行,babel的preset也要重新写,不然读取不到:
7.回到gulp-demo
项目,运行yarn gulp build
就正常打包了,ok,第一步调试完成;
2.抽象路径和形成可配置
更改lib/index.js文件,把所有目录改成间接的目录地址,以后我们只要在page.config.js配置文件里传build参数覆盖默认的就行了,如下:
(yw-gulpfile项目的lib/index.js文件)
//入口文件
const { src, dest, parallel, series, watch } = require("gulp")
const del = require("del")
const loadPlugins = require("gulp-load-plugins")
const plugins = loadPlugins()
/**2.自动加载插件 */
const sass = require("gulp-sass")(require("sass"))//因为新版本不内置sass,这里就手动版吧
// const babel = require("gulp-babel")
// const swig = require("gulp-swig")
// const imagemin = require("gulp-imagemin")
/**3.启动小服务 */
const browserSync = require("browser-sync")
const bs = browserSync.create();
const cwd = process.cwd(); //定位到宿主的根目录
let config = {
//默认配置
build: {
src: 'src',
dist: "dist",
temp: 'temp',
public: 'public',
paths: {
styles: "assets/styles/*.scss",
scripts: "assets/scripts/*.js",
pages: "*.html",
images: 'assets/images/**',
fonts: "src/assets/fonts/**"
}
}
}
try {
const loadConfig = require(`${cwd}/page.config.js`)
config = Object.assign({}, config, loadConfig)
} catch (e) {
//不用处理
console.log('e: ', e);
}
const clean = () => {
return del([config.build.dist, config.build.temp])
}
//可以拼接的方式,也可以直接配置
const style = () => {
return src(config.build.paths.styles, { base: config.build.src, cwd: config.build.src })
.pipe(sass({ outputStyle: 'expanded' }))
.pipe(dest(config.build.temp))
.pipe(bs.reload({ stream: true }))
}
const script = () => {
return src(config.build.paths.scripts, { base: config.build.src, cwd: config.build.src })
.pipe(plugins.babel({ presets: [require("@babel/preset-env")] }))
.pipe(dest(config.build.temp))
.pipe(bs.reload({ stream: true }))
}
const page = () => {
return src(config.build.paths.pages, { base: config.build.src, cwd: config.build.src })
.pipe(plugins.swig({ data: config.data, defaults: { cache: false } }))
.pipe(dest(config.build.temp))
.pipe(bs.reload({ stream: true }))
}
const image = () => {
return src(config.build.paths.images, { base: config.build.src, cwd: config.build.src })
.pipe(plugins.imagemin())
.pipe(dest(config.build.dist))
}
const font = () => {
return src(config.build.paths.fonts, { base: config.build.src, cwd: config.build.src })
.pipe(plugins.imagemin())
.pipe(dest(config.build.dist))
}
const extra = () => {
return src("**", { base: config.build.public, cwd: config.build.public })
.pipe(dest(config.build.dist))
}
const useref = () => {
return src(config.build.paths.pages, { base: config.build.temp, cwd: config.build.temp })
.pipe(plugins.useref({ searchPath: [config.build.temp, '.'] }))
//读取了html中所有引入的css,js的引入路径文件(包含本地和第三方)
//这里读出了html,css,js三种格式文件,需要使用压缩插件gulp-htmlmin,gulp-uglify,gulp-clean-css,使用gulp-if判断文件流类型
.pipe(plugins.if(/\.js$/, plugins.uglify()))
.pipe(plugins.if(/\.css$/, plugins.cleanCss()))
.pipe(plugins.if(/\.html$/, plugins.htmlmin({
collapseWhitespace: true,
minifyCSS: true,
minifyJS: true
})))
// .pipe(dest('dist')) //会有读写混乱的问题
.pipe(dest(config.build.dist))
}
const server = () => {
watch(config.build.paths.styles, { cwd: config.build.src }, style)
watch(config.build.paths.scripts, { cwd: config.build.src }, script)
watch(config.build.paths.pages, { cwd: config.build.src }, page)
//dev环境,不监听这些文件,因为只涉及到搬运文件和压缩,无编译
// watch("src/assets/images/**", image)
// watch("src/assets/fonts/**", font)
// watch("public/**", extra)
//图片字体发生变化刷新浏览器,需要分开写,因为目录不一样
watch([
config.build.paths.images,
config.build.paths.fonts,
], { cwd: config.build.src }, bs.reload)
watch(["**"], { cwd: config.build.public }, bs.reload)
bs.init({
notify: false,
port: 4090,
// files: 'dist/**',//当不使用这个监听方式时,需要在对应的任务的pipe里加上.pipe(bs.reload({ stream: true })),如上的style和js,html
server: {
//开发环境可以匹配"src", "public"下的字体或者图片
baseDir: [config.build.temp, config.build.src, config.build.public],
routes: {
//优先级最高
"/node_modules": "node_modules"
}
}
})
}
const compile = parallel(style, script, page)
//转义-》搬运和压缩图片和字体-》压缩html、js、css
const build = series(
clean,
parallel(
series(compile, useref),
image,
font,
extra
))
//dev环境不做图片和字体等的搬运和压缩,只进行转换(js、scss等)
const develop = series(compile, server)
module.exports = {
clean,
build,
develop
}
回到回到
gulp-demo
项目,运行yarn gulp build
,能正常打包,ok,完事了
3.用cli命令执行 和 发布到npm仓库
(1)用cli命令执行
到这你会发现,
gulp-demo
项目下还有gulpfile.js文件,那能不能直接不要这个文件,我只要执行命令,就知道我的gulpfile.js是使用的yw-gulpfile项目里的入口文件(lib/index.js);可以的,方式如下:
a) 直接在gulp-demo
项目的npm script里配置执行命令 :gulp build --gulpfile ./node_modules/yw-gulpfile/lib/index.js --cwd .
运行yarn build
就能正常打包了。(—cwd 是指定工作目录,.为当前目录)
b)我们可以在yw-gulpfile项目里提供一个bin cli来执行传参和调用gulp cli就行了,具体操作如下:
图一
图二
(如图一)在yw-gulpfile项目下新建bin/yw.js,然后在package.json里配置bin就好了,然后回到
gulp-demo
项目重新走一遍yarn link就好了;
(如图二) 在bin/jw.js里写上bin命令就好了(注意:#!/usr/bin/env node这个注释必须写,才能设别成bin命令文件),最后回到gulp-demo
项目执行yw build
就能正常打包了
(2)发布成npm包
- 去npm官网注册账号,官网:https://www.npmjs.com/
- 先把yw-gulpfile项目提交到github上
先github建立yw-gulpfile仓库,回到本地yw-gulpfile项目,在命令行输入:
git remote add origin https://github.com/usefire/yw-gulpfile.git
,然后git add和commit,再git push -u origin master
,最后修改一下package.json就可以准备发布了;如下:
{
"name": "yw-gulpfile",
"version": "1.0.1",
"description": "this is a test",
"main": "lib/index.js",
"bin": {
"yw": "bin/yw.js"
},
"directories": {
"lib": "lib"
},
"author": "usefire",
"license": "MIT",
"keywords": [
"gulpfile",
"yw",
"yw-gulpfile"
],
"homepage": "https://github.com/usefire/yw-gulpfile",
"bugs": {
"url": "https://github.com/usefire/yw-gulpfile/issues"
},
"repository": {
"type": "github",
"url": "https://github.com/usefire/yw-gulpfile.git"
},
"files": [
"lib",
"bin"
],
"scripts": {
"lint": "standard --fix"
},
"dependencies": {
"@babel/core": "^7.21.3",
"@babel/preset-env": "^7.20.2",
"browser-sync": "^2.29.1",
"caz": "^1.1.0",
"del": "^5.1.0",
"gulp": "^4.0.2",
"gulp-babel": "^8.0.0",
"gulp-clean-css": "^4.3.0",
"gulp-htmlmin": "^5.0.1",
"gulp-if": "^3.0.0",
"gulp-imagemin": "^7.1.0",
"gulp-load-plugins": "^2.0.8",
"gulp-sass": "^5.1.0",
"gulp-swig": "^0.9.1",
"gulp-uglify": "^3.0.2",
"gulp-useref": "^5.0.0",
"sass": "^1.60.0"
},
"devDependencies": {
"standard": "^17.0.0"
}
}
- 在把
yw-gulpfile
项目下控制台输入npm login
登录npm,然后执行npm publish,好了发布完成; - 回到
gulp-demo
项目,装上该插件:yarn add yw-gulpfile --dev
,然后执行yarn yw build
就能正常 打包啦
四、总结
官方文档:[https://www.gulpjs.com.cn/](https://www.gulpjs.com.c n/)