vue3企业级组件库封装[五]:gulp的使用
五、前端流程化控制工具gulp的使用
如webpack,rollup,vite的发展,gulp感觉似乎好像被取代了。其实并没有,只不过它从台前退居到
了幕后。我们仍然可以在很多项目中看到它的身影,比如elementplus、vant等。现在gulp更多的是做
流程化的控制。
比如我们要把一个东西放进冰箱里就需要 打开冰箱门->把东西放进冰箱->关上冰箱门,这就是一个简单的流程,使用gulp就可以规定这些流程,将这个流程自动化。
所以我们可以使用它在项目开发过程中自动执行常见任务。比如打包一个组件库,我们可能要移除文
件、copy文件,打包样式、打包组件、执行一些命令还有一键打包多个package等等都可以由gulp进行自定义流程的控制,非常的方便。
1、介绍gulp主要的一些常用功能
首先全局安装gulp的脚手架
npm install --global gulp-cli
然后我们新建文件夹gulpdemo,然后执行 npm init -y,然后在这个项目下安装本地依赖gulp
npm install gulp -D
此时我们gulp便安装好了,接下来我们在根目录下创建gulpfile.js文件,当gulp执行的时候会自动寻找
这个文件。
2、创建一个任务Task
每个gulp任务(task)都是一个异步的JavaScript函数,此函数是一个可以接收callback作为参数的函
数,或者返回一个Promise等异步操作对象,比如创建一个任务 可以这样写
exports.default = (cb) => {
console.log("my task");
cb();
};
或者这样写
exports.default = () => {
console.log("my task");
return Promise.resolve();
};
然后终端输入gulp就会执行我们这个任务。
3、串行(series)和并行(parallel)
这两个其实很好理解,串行就是任务一个一个执行,并行就是所有任务一起执行。下面先看串行演示
const { series, parallel } = require("gulp");
const task1 = () => {
console.log("task1");
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 5000);
});
};
const task2 = () => {
console.log("task2");
return Promise.resolve();
};
exports.default = series(task1, task2);
执行 =》在控制台 输入 gulp
控制台输出结果如下

可以看出执行task1用了4s,然后再执行task2,再看下并行

可以看出两个任务是同时执行的
4、src()和dest()
src()和dest()这两个函数在我们实际项目中经常会用到。src()表示创建一个读取文件系统的流,dest()
是创建一个写入到文件系统的流。我们直接写一个copy 的方法
5、复制某个文件流
在写之前我们先在我们项目根目录下新建一个src目录用于存放我们被复制的文件,在src下随便新建几
个文件,如下图

然后我们在gulpfile.js写下我们的copy任务:将src下的所有文件复制到dist文件夹下:
//我们在这里写copy任务
const {src,dest} = require('gulp');
//src => 读取文件
//dest => 写入文件
const copy = () => {
//pipe => 管道流
return src('src/*').pipe(dest('dist'));
}
exports.default = copy;
然后执行gulp(默认执行exports.default),我们就会发现根目录下多了个dist文件夹
6、写个处理less文件的任务
那么通过上面的认识 =》处理样式=》我这里是less文件。
下面我们写个处理less文件的任务,首先我们先安装gulp-less。
npm i -D gulp-less
然后我们在src下新建一个style/index.less并写下一段less语法样式
index.less
@color: #7f0f0f;
.wukong {
color: @color;
}
然后gulpfile.js写下我们的lessTask:将我们style下的less文件解析成css并写入dist/style中
//现在我们需要处理less文件=>将他们转换成css文件=》写到dist目录下
//读取和写入文件
const { src, dest } = require('gulp');
//引入gulp-less =》将less文件转换成css文件
const less = require('gulp-less');
//引入gulp-clean-css =》压缩css文件(组件库中使用)
//写一个任务
function lessTask() {
return src('src/style/*.less') //读取文件
.pipe(less()) //将less文件转换成css文件
.pipe(dest('./dist/style')) //写入文件
}
exports.default = lessTask; //导出任务
然后我们执行gulp命令就会发现dist/style/index.css
dist/style/index.css
.wukong {
color: #7f0f0f;
}
我们还可以给css加前缀 =>来兼容不同的浏览器 =》需要引入插件
npm install gulp-autoprefixer -D
将我们的src/style/index.less改为
@color: #7f0f0f;
.wukong {
color: @color;
display: flex;
}
然后在gulpfile.js中使用gulp-autoprefixer
import {src, dest } from 'gulp'
import less from 'gulp-less'
//引入兼容不同的浏览器前缀
import autoprefixer from 'gulp-autoprefixer'
//写一个任务
function lessTask() {
return src('src/style/*.less') //读取文件
.pipe(less()) //将less文件转换成css文件
.pipe(autoprefixer({
overrideBrowserslist: ["> 1%", "last 2 versions"]
})) //添加前缀
.pipe(dest('./dist/style')) //写入文件
}
export default lessTask; //导出任务
在将packages.json文件中添加
"type": "module"
7、压缩css文件
在前端开发中,优化代码性能是至关重要的一步,尤其是CSS文件,过大的尺寸可能导致页面加载速度变慢。今天,我将向您推荐一个强大的CSS压缩工具—— gulp-clean-css ,它是基于Gulp的任务自动化工具]和Clean CSS库的完美结合。
gulp-clean-css 是一个Gulp插件,用于压缩和清理CSS文件。它利用了Clean CSS库的强大功能,提供了一种简单、高效的途径来减小CSS文件的大小,从而提升网页加载速度。
安装依赖
npm install --save-dev gulp-clean-css
在你的 gulpfile.js 中引入并创建任务:
//现在我们需要处理less文件=>将他们转换成css文件=》写到dist目录下
//读取和写入文件
// const { src, dest } = require('gulp');
// //引入gulp-less =》将less文件转换成css文件
// const less = require('gulp-less');
// const autoprefixer = require("gulp-autoprefixer");
import {src, dest } from 'gulp'
import less from 'gulp-less'
//引入兼容不同的浏览器前缀
import autoprefixer from 'gulp-autoprefixer'
//引入gulp-clean-css =》压缩css文件(组件库中使用)
import cleanCSS from 'gulp-clean-css'
//写一个任务
function lessTask() {
return src('src/style/*.less') //读取文件
.pipe(less()) //将less文件转换成css文件
.pipe(autoprefixer({
overrideBrowserslist: ["> 1%", "last 2 versions"]
})) //添加前缀
.pipe(cleanCSS()) //压缩css文件
.pipe(dest('./dist/style')) //写入文件
}
// exports.default = lessTask; //导出任务
export default lessTask; //导出任务
处理后的dist/style/index.css就变成了
.wukong{color:#7f0f0f;display:-webkit-box;display:-ms-flexbox;display:flex}
8、监听文件更改browser-sync
browser-sync是一个十分好用的浏览器同步测试工具,它可以搭建静态服务器,监听文件更改,并刷
新页面(HMR),下面来看下它的使用
首先肯定要先安装
npm i browser-sync -D
然后我们在根目录下新建index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./dist/style/index.css" />
</head>
<body>
hello world
</body>
</html>
然后在gulpfile.js中进行配置 将之前的gulpfile.js变成gulpfile1.js 保留内容
//写一个任务 监听文件变化
import browserSync from "browser-sync";
const browserTask = () => {
browserSync.init({
server: {
baseDir: './' // 从这个项目的根目录提供文件
}
});
}
export default browserTask;
这时候就会启动一个默认3000端口的页面. 下面我们看如何监听页面变化。
首先我们要监听文件的改变,可以使用browserSync的watch,监听到文件改变后再刷新页面
此时改动src下的文件浏览器便会刷新。
下面我们将index.html引入dist/style/index.css的样式,然后来模拟一个简单的构建流
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./dist/style/index.css" />
</head>
<body>
<div class="wukong">
悟空前端
</div>
</body>
</html>
此时我们的流程是 编译less文件->将css写入dist/style->触发页面更新
我们gulpfile.js可以这样写
import {src, dest } from 'gulp'
import less from 'gulp-less'
import autoprefixer from 'gulp-autoprefixer'
import cleanCSS from 'gulp-clean-css'
//写一个任务 监听文件变化
import browserSync from "browser-sync";
import {watch} from 'browser-sync'
//watch =>作用:监听文件变化
import {series} from 'gulp'
//series =>作用:串行执行任务
//引入需要监听的任务less
function lessTask() {
return src('src/style/*.less') //读取文件
.pipe(less()) //将less文件转换成css文件
.pipe(autoprefixer({
overrideBrowserslist: ["> 1%", "last 2 versions"]
})) //添加前缀
.pipe(cleanCSS()) //压缩css文件
.pipe(dest('./dist/style')) //写入文件
}
//监听页面刷新
const reload = (done) => {
browserSync.reload(); //刷新页面
}
const browserTask = () => {
browserSync.init({
server: {
baseDir: './' // 从这个项目的根目录提供文件
}
});
watch('./*.html', series(reload)); //HTML文件发生变化时,执行reload任务
watch('src/style/*', series(lessTask,reload))
}
export default browserTask;
此时无论我们更改的是样式还是html都可以触发页面更新。
六、使用gulp打包组件库并实现按需加载
使用 Vite 库模式打包的时候,vite 会将样式文件全部打包到同一个文件中,这样的话我们每次都要全量引
入所有样式文件做不到按需引入的效果。所以打包的时候我们可以不让 vite 打包样式文件,样式文件将
使用 gulp 进行打包 ,
将介绍如何使用 gulp 打包样式文件,以及如何按需加载样式文件。
1、自动按需引入插件
现在很多组件库的按需引入都是借助插件来解决的,比如 ElementPlus 是使用 unplugin-vue- components 和 unplugin-auto-import ,这两个插件可以实现
比如
import { Button } from "wukongui";
//相当于
import "wukongui/es/src/button/style/index.css";
import "wukongui/es/src/button/index.mjs";
2、删除打包文件
我们都知道,在打包之前是需要将前面打包的文件删除的,所以需要先写一个删除函数。在此之前,我们先在 components 新建一个 script 文件夹用于存放我们的脚本相关内容,script 下的 build 文件夹里的内
容则是本篇文章要介绍的打包相关内容。
在 script/utils 中新建 paths.ts 用于维护组件库路径,记得先安装
pnpm add @types/node -D -w
import { resolve } from "path";
//组件根目录
export const componentPath = resolve(__dirname, "../../");
//打包组件的根目录
export const pkgPath = resolve(__dirname, "../../../");
删除打包目录函数可以放在 bulid/utils 中的 delpath.ts,注意这里因为打包后的 wukongui 包是我们最
终要发布的包,所以我们需要将 package.json 和 README.md 保留下来
import fs from "fs"; //作用:读取文件
import { resolve } from "path"; //作用:解析路径
import { pkgPath } from "./path";
//需要保留的文件
const keepFiles = ["package.json", "README.md"];
//需要删除的文件
const deleteFiles = async (path: string) => {
let files: string[] = [];
if (fs.existsSync(path)) {
//判断文件是否存在
files = fs.readdirSync(path); //读取文件夹下的文件
files.forEach(async (file) => {
const curPath = resolve(path, file); //拼接路径
if (fs.statSync(curPath).isDirectory()) {
//判断是否是文件夹
if (file != "node_modules") await deleteFiles(curPath);
} else {
if (!keepFiles.includes(file)) {
//判断是否是需要保留的文件
fs.unlinkSync(curPath); //删除文件
}
}
});
if (path !== pkgPath) {
fs.rmdirSync(path); //删除文件夹
}
}
};
export default deleteFiles;
3、使用gulp
我们需要使用 ts 以及新的 es6 语法,而 gulp 是不支持的,所以我们需要安装一些依赖使得 gulp 支持
这些,其中 sucras 让我们执行 gulp 可以使用最新语法并且支持 ts
pnpm i gulp @types/gulp sucrase -D -w
在 build/index.ts 来执行删除流程
import delPath from "../utils/delpath";
import { series, parallel } from "gulp";
import { pkgPath } from "../utils/paths";
//删除dist目录
export const removeDist = () => {
return delPath(`${pkgPath}/wukongui`);
};
export default series(async () => removeDist());
在根目录wukongui/package.json 添加脚本
"scripts": {
"build:wukong": "gulp -f packages/components/script/build/index.ts"
},
根目录下执行`pnpm run build:wukong就会发现 dist 下的文件被删除了
4、gulp打包样式
因为我们用的是 less 写的样式,所以需要安装 gulp-less ,同时在安装一个自动补全 css 前缀插件 gulpautoprefixer 以及它们对应的上面文件
pnpm add gulp-less @types/gulp-less gulp-autoprefixer @types/gulp-autoprefixer -
D -w
export const buildStyle = () => {
return src(`${componentPath}/src/**/style/**.less`)
.pipe(less())
.pipe(autoprefixer())
.pipe(dest(`${pkgPath}/dist/lib/src`))
.pipe(dest(`${pkgPath}/dist/es/src`));
}
5、打包组件
最后再写一个打包组件的函数,这里需要写一个执行命令的工具函数,在 utils/run.ts
import { spawn } from "child_process";//nodejs内置模块,用于执行命令
export default async (command: string, path: string) => {
//cmd表示命令,args代表参数,如 rm -rf rm就是命令,-rf就为参数
const [cmd, ...args] = command.split(" ");
return new Promise((resolve, reject) => {
const app = spawn(cmd, args, {
cwd: path, //执行命令的路径
stdio: "inherit", //输出共享给父进程
shell: true, //mac不需要开启,windows下git base需要开启支持
});
//执行完毕关闭并resolve
app.on("close", resolve);
});
};
然后引入 run 函数
export const buildComponent = async () => {
run("pnpm run build", componentPath);
};
因为打包样式和打包组件可以并行,所以最后 build/index.ts 为
import deleteFiles from "../utils/delpath";
import { series, src, dest, parallel } from "gulp";
import { pkgPath, componentPath } from "../utils/path";
import less from "gulp-less";
import autoprefixer from "gulp-autoprefixer";
import run from "../utils/run";
//使用gulp打包样式
export const buildStyle = () => {
return src(`${componentPath}/src/**/style/**.less`)
.pipe(less())
.pipe(autoprefixer())
.pipe(dest(`${pkgPath}/dist/lib/src`))
.pipe(dest(`${pkgPath}/dist/es/src`));
};
export const removeDist = () => { //删除dist目录
return deleteFiles(`${pkgPath}/dist`);
};
//打包组件
export const buildComponent = async () => {
run("pnpm run build", componentPath); //执行命令
};
export default series(
async () => removeDist(),
parallel( //并行执行
async () => buildStyle(), //打包样式
async () => buildComponent()//
)
);
最后 vite 打包的时候忽略 less 文件,components/vite.config.ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import dts from "vite-plugin-dts";
import DefineOptions from "unplugin-vue-define-options/vite";
export default defineConfig({
build: {
//打包文件目录
outDir: "es",
//压缩
//minify: false,
rollupOptions: {
//忽略打包vue和.less文件
external: ["vue", /\.less/],
...
}
});
打包效果图 =>根目录执行 pnpm run build ,即可完成打包


3485

被折叠的 条评论
为什么被折叠?



