前言
这一篇文章我们将实现组件库打包与发布的自动化,将我们从繁琐的打包和发布流程中解救出来(如:打包前要删除打包文件,发布前要增加版本号、修改package.json、每个包都要执行打包命令等等等等)。同时我们的组件样式的打包也将采用gulp流程化控制。如果你不太了解gulp,你可以先花十分钟时间看下前端自动化工具gulp急速入门这篇文章。如果你对vue3组件库开发感兴趣的话,你也可以先阅读前置文章使用Vite和TypeScript带你从零打造一个属于自己的Vue3组件库。当然你也可以直接阅读本篇文章,每一步我都会有详细的解释说明。相信看完这篇文章你就会发现使用gulp自动化流程带来的魅力。
我们要用gulp做什么?
我们要用gulp处理我们的打包流程和发布流程,如下图所示
让gulp支持ts和es6
我们需要使用ts以及新的es6语法,而gulp是不支持的,所以我们需要安装一些依赖使得gulp支持这些
-
gulp
-
@types/gulp gulp的ts声明文件
-
sucras 让我们执行gulp可以使用最新语法并且支持ts
pnpm i gulp @types/gulp sucrase -D -w
测试gulp
我们在根目录的package.json添加打包组件库脚本命令
... "scripts": { "build:kitty": "gulp -f packages/components/script/build/gulpfile.ts"
}
...
根目录执行npm run build:kittygulp去执行packages/components/script/build/gulpfile.ts,所以在packages/components下新建gulpfile.ts并写个测试的脚本,看下我们的gulp是否生效
export default () => { console.log('任务完成') return Promise.resolve()
}
然后我们执行npm run build:kitty就会发现gulpfile.ts被执行了
接下来我们就可以使用gulp来实现我们的自动化流程了
删除dist文件夹
在打包之前我们首先是要删除我们上一次打包留下的dist文件的.我们通常删除一个文件夹只需要在cmd中输入rm -rf xxx即可,所以说我们需要写一个执行脚本命令的任务,而Node.js的子进程 child_process
模块下有一 spawn
函数,可以用于调用系统上的命令。所以我们可以利用它来实现这个任务函数。因为我们是在项目根目录下执行的,所以在实现这个函数前我们还需要维护一些路径信息。
script下新建utils/paths.ts,以后的路径信息都放在这
import { resolve } from 'path'//组件库根目录export const componentPath = resolve(__dirname, '../../')
script/build/gulpfile.ts
import { spawn } from 'child_process'import { series } from 'gulp'import { componentPath } from '../utils/paths'console.log(componentPath);const run = async (command: string) => { //cmd表示命令,args代表参数,如 rm -rf rm就是命令,-rf就为参数
const [cmd, ...args] = command.split(' ') return new Promise((resolve, reject) => { const app = spawn(cmd, args, { cwd: componentPath,//执行命令的路径
stdio: 'inherit', //输出共享给父进程
shell: true
}) //执行完毕关闭并resolve
app.on('close', resolve)
})
}export default series(async () => run(`rm -rf ${componentPath}/dist`))
因为我们还没有打包所以组件库目录下还没有dist文件夹,所以我们先暂时新建个dist文件夹模拟一下,我们的目录结构如下
然后在根目录下执行pnpm run build:kitty我们就会发现dist目录被删除了,此时我们的删除dist命令便完成了
注意
如果你的vscode终端没有配置git base
是无法执行rm -rf
这种命令的,所以你需要给你的vscode终端配置git base
,配置方法如图示:
"terminal.integrated.profiles.windows": { "bash": { "path": "D:\Git\bin\bash.exe", // 找到自己git安装目录所在xxxbash.exe
"args": []
}
}
打包流程控制
接下来我们开始我们的组件库打包流程控制,打包组件库我们分为打包组件和打包样式两部分
处理样式
处理样式之前我们要安装一些依赖
pnpm i gulp-less @types/gulp-less gulp-autoprefixer @types/gulp-autoprefixer -D -w
其中gulp-less
是gulp中处理less的插件,gulp-autoprefixer
是为css加前缀的的插件。@types/xxx则是它们的声明文件
然后写一个处理样式的任务buildStyle
//script/build/gulpfile.tsimport { spawn } from 'child_process'import { series, src, dest, task } from 'gulp'import { componentPath } from '../utils/paths'import less from "gulp-less"import autoprefixer from 'gulp-autoprefixer'const run = async (command: string) => { //cmd表示命令,args代表参数,如 rm -rf rm就是命令,-rf就为参数
const [cmd, ...args] = command.split(' ') return new Promise((resolve, reject) => { const app = spawn(cmd, args, { cwd: componentPath,//目录指的是组件库根目录
stdio: 'inherit', //输出共享给父进程
shell: true //mac不需要开启,windows下git base需要开启支持
}) //执行完毕关闭并resolve
app.on('close', resolve)
})
}//处理样式const buildStyle = () => { return src(`${componentPath}/src/**/style/**.less`)
.pipe(less())
.pipe( autoprefixer()
)
.pipe(dest(`${componentPath}/dist/lib`))
.pipe(dest(`${componentPath}/dist/es`));
};export default series(async () => run(`rm -rf ${componentPath}/dist`), async () => buildStyle())
我们会发现gulp处理方式是以流的方式一层一层往下走,最后走到我们打包后的目录下。
然后我们根目录执行pnpm run build:kitty
,就会发现样式被打包进了dist文件中
控制台输出如下
dist文件如下
组件打包
接下来就是组件的打包,详细的流程可以参考使用Vite和TypeScript带你从零打造一个属于自己的Vue3组件库,这里对原来的components/vite.config.ts做一个条调整
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue"import dts from 'vite-plugin-dts'import { resolve } from 'path'export default defineConfig(
{ build: { target: 'modules',
//打包文件目录 outDir: "es",
//压缩 minify: true,
//css分离
//cssCodeSplit: true, rollupOptions: {
//忽略打包vue文件 external: ['vue', /.less/], input: ['src/index.ts'], output: [
{ format: 'es',
//不用打包成.es.js,这里我们想把它打包成.js entryFileNames: '[name].js',
//让打包目录和我们目录对应 preserveModules: true,
//配置打包根目录 dir: resolve(__dirname, './dist/es'), preserveModulesRoot: 'dist'
},
{ format: 'cjs',
//不用打包成.mjs entryFileNames: '[name].js',
//让打包目录和我们目录对应 preserveModules: true,
//配置打包根目录 dir: resolve(__dirname, './dist/lib'), preserveModulesRoot: 'src'
}
]
}, lib: { entry: './index.ts', formats: ['es', 'cjs']
}
}, plugins: [ vue(), dts({ outputDir: resolve(__dirname, './dist/es'),
//指定使用的tsconfig.json为我们整个项目根目录下掉,如果不配置,你也可以在components下新建tsconfig.json tsConfigFilePath: '../../tsconfig.json'
}),
//因为这个插件默认打包到es下,我们想让lib目录下也生成声明文件需要再配置一个 dts({ outputDir: resolve(__dirname, './dist/lib'), tsConfigFilePath: '../../tsconfig.json'
}),
{ name: 'style', generateBundle(config, bundle) {
//这里可以获取打包后的文件目录以及代码code const keys = Object.keys(bundle) for (const key of keys) { const bundler: any = bundle[key as any] //rollup内置方法,将所有输出文件code中的.less换成.css,因为我们当时没有打包less文件
this.emitFile({ type: 'asset', fileName: key,//文件名名不变 source: bundler.code.replace(/.less/g, '.css')
})
}
}
}
],
resolve: {
alias: { '@': resolve(__dirname, 'src'),
},
}
}
)
主要将原来的打包路径以及声明文件路径指向了dist目录下。
然后我们写个打包组件函数buildComponent
//打包组件const buildComponent = async () => { await run(`cd ${componentPath}`) run('pnpm run build')
}
其实步骤很简单,就是在组件库根目录(packages/componmets/)执行pnpm run build
,所以components/package.json的脚本命令改为
"scripts": {
"build": "vite build"
}
由于我们打包组件和打包样式是互不影响的,所以这两部分可以并行执行parallel
,此时我们的gulpfile.ts
可以这样写
import { series, src, dest, parallel } from 'gulp'
...//打包组件const buildComponent = async () => {
await run(`cd ${componentPath}`) run('pnpm run build')
}
export default series(
async () => run(`rm -rf ${componentPath}/dist`), parallel(
async () => buildStyle(),
async () => buildComponent()
)
)
根目录执行pnpm run build:kitty
便可完成我们的组件与样式的打包,打包后的目录如图所示
发布流程
接下来我们要做的就是发布了,因为我们需要在dist下进行发布,所以我们要做的就是先往dist下塞一个用于发布的package.json
,这个package.json
我们要在组件库下新建个中转的package.json
复制到dist下。
在components下新建transitpkg/package.json
{
"name": "kitty-ui",
"version": "1.0.0",
"main": "lib/index.js",
"module": "es/index.js",
"files": ["es", "lib"],
"keywords": ["kitty-ui", "vue3组件库"],
"author": "小月",
"license": "MIT",
"description": "",
"typings": "lib/index.d.ts"}
根目录下package.json新增命令pnpm run publish:kitty
"scripts": {
"build:kitty": "gulp -f packages/components/script/build/gulpfile.ts",
"publish:kitty": "gulp -f packages/components/script/publish/gulpfile.ts"
}
同样的我们新建packages/components/script/publish/gulpfile.ts,(相关注释写在代码中)
import { spawn } from 'child_process'import { series, src, dest } from 'gulp'import { componentPath } from '../utils/paths'const run = 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)
})
}//复制const copypackage = async () => { return src(`${componentPath}/transitpkg/**`).pipe(dest(`${componentPath}/dist/`));
};//发布任务const publish = async () => { //先给transitpkg升个版本
await run('pnpm version patch', `${componentPath}/transitpkg`) //复制到dist目录
await copypackage() //在dist下执行发布命令
await run('npm publish', `${componentPath}/dist`) // run('pnpm publish')}export default series( async () => publish()
)
最后我们执行pnpm run publish:kitty
便可发布我们的组件库。其实这里的一些方法可以提取到utils中,gulp的任务函数也可以写到其它地方,gulpfile.ts只作为一个集中执行的地方。具体 目录如下
相关代码可以到 kittyui 查看。
到这里我们的组件库已经可以自动打包和发布了
直接使用
-
拉取kittyui
git clone https://gitee.com/geeksdidi/kittyui.git
-
安装pnpm
npm i pnpm -g
-
安装esno
npm i esno -g
-
安装项目所有依赖
pnpm install
-
打包组件库
pnpm run build:kitty
-
发布组件库
发布前记得到components/transitpkg/package.json下改个包名(不然肯定会重名,因为我已经发布过了)
pnpm run publish:kitty
最后
如果你对组件库开发感兴趣的话可以关注Vite+TypeScript从零搭建Vue3组件库 – 东方小月的专栏 – 掘金 (juejin.cn),后续将不断完善组件库,一步步实现所有常用组件。
创作不易,你的点赞就是我的动力!如果感觉这篇文章对你有帮助的话就请点个赞吧,谢谢谢!!
原文始发于微信公众号(web前端进阶):从0搭建Vue3组件库:使用gulp自动化处理打包与发布
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/232554.html