【前端工程化-组件库】从0-1构建Vue3组件库(打包发布)
前言
前面篇章我们已经完成了开源组件库编码,接下来需要做的是打包发布到 NPM 上。我们来大致梳理下实现思路:
编译打包
组件库需要做 2 种打包方式:全量打包、单组件打包,以提供给第三方调用者灵活选择使用。
打包方式:
- 全量打包:打包全部组件
- 按需打包:单个组件打包,⽤户单独引⼊
全量组件打包
我们先来做全量组件打包,整体思路如下:
- 创建打包文件 build.js;
- 读取组件库的全局入口,设置为 entry;设置 outputDir 输出目录为 build 目录;
- 使用vite build配置编译参数;
- 使用node fs生成package.json。
具体代码实现如下:
scripts/build.js
const path = require("path")
const fs = require("fs-extra")
// 引入 vite 的 build 方法,进行编译构建
const { defineConfig, build } = require("vite")
const vue = require("@vitejs/plugin-vue")
const vueJSX = require("@vitejs/plugin-vue-jsx")
const version = require("../package.json").version
// 基础配置
const baseConfig = defineConfig({
publicDir: false,
plugins: [vue(), vueJSX()]
})
const rollupOptions = defineConfig({
// that shouldn't be bundled
external: ["vue"],
globals: {
vue: "Vue"
}
})
// 组件库全局入口
const compontsDir = path.resolve(__dirname, "../packages/components")
// 输出目录
const outputDir = path.resolve(__dirname, "../build")
// 生成 package.json
const createPackageJson = name => {
const fileStr = `{
"name": "${name ? name : "pc-vue3-ui"}",
"version": "${version}",
"description": "Vue3组件库",
"main": "${name ? "index.umd.js" : "pc-vue3-ui.umd.js"}",
"module":"${name ? "index.mjs" : "pc-vue3-ui.mjs"}",
"repository": {
"type": "git",
"url": "git+https://github.com/GGXXMM/vue3-ui.git"
},
"keywords": ["vue3", "组件库", "UI"],
"author": "guoxinming",
"license": "ISC"
}
`
// 单个组件 or 全量
const filePath = path.resolve(
outputDir,
name ? `${name}/package.json` : `package.json`
)
fs.outputFile(filePath, fileStr, "utf-8")
}
/** 全量构建 */
const buildAll = async () => {
await build(
defineConfig({
...baseConfig,
build: {
lib: {
entry: compontsDir,
name: "pc-vue3-ui",
fileName: "pc-vue3-ui",
formats: ["es", "umd"]
},
rollupOptions,
outDir: outputDir
}
})
)
createPackageJson()
}
单组件打包
单组件打包,与全量打包的主要差异是获取打包入口和出口。入口entry是单组件的index.ts,输出outputDir则设置为 build 目录下的具体组件。代码实现如下所示:
const path = require("path")
const fs = require("fs-extra")
// 引入 vite 的 build 方法,进行编译构建
const { defineConfig, build } = require("vite")
const vue = require("@vitejs/plugin-vue")
const vueJSX = require("@vitejs/plugin-vue-jsx")
const version = require("../package.json").version
// 基础配置
const baseConfig = defineConfig({
publicDir: false,
plugins: [vue(), vueJSX()]
})
const rollupOptions = defineConfig({
// that shouldn't be bundled
external: ["vue"],
globals: {
vue: "Vue"
}
})
// 组件库全局入口
const compontsDir = path.resolve(__dirname, "../packages/components")
// 输出目录
const outputDir = path.resolve(__dirname, "../build")
// 生成 package.json
const createPackageJson = name => {
const fileStr = `{
"name": "${name ? name : "pc-vue3-ui"}",
"version": "${version}",
"description": "Vue3组件库",
"main": "${name ? "index.umd.js" : "pc-vue3-ui.umd.js"}",
"module":"${name ? "index.mjs" : "pc-vue3-ui.mjs"}",
"repository": {
"type": "git",
"url": "git+https://github.com/GGXXMM/vue3-ui.git"
},
"keywords": ["vue3", "组件库", "UI"],
"author": "guoxinming",
"license": "ISC"
}
`
// 单个组件 or 全量
const filePath = path.resolve(
outputDir,
name ? `${name}/package.json` : `package.json`
)
fs.outputFile(filePath, fileStr, "utf-8")
}
/** 单组件按需构建 */
const buildSingle = async name => {
await build(
defineConfig({
...baseConfig,
build: {
lib: {
entry: path.resolve(compontsDir, name),
name: "index",
fileName: "index",
formats: ["es", "umd"]
},
rollupOptions,
outDir: path.resolve(outputDir, name)
}
})
)
createPackageJson(name)
}
完整代码
const path = require("path")
const fs = require("fs-extra")
// 引入 vite 的 build 方法,进行编译构建
const { defineConfig, build } = require("vite")
const vue = require("@vitejs/plugin-vue")
const vueJSX = require("@vitejs/plugin-vue-jsx")
const version = require("../package.json").version
// 基础配置
const baseConfig = defineConfig({
publicDir: false,
plugins: [vue(), vueJSX()]
})
const rollupOptions = defineConfig({
// that shouldn't be bundled
external: ["vue"],
globals: {
vue: "Vue"
}
})
// 组件库全局入口
const compontsDir = path.resolve(__dirname, "../packages/components")
// 输出目录
const outputDir = path.resolve(__dirname, "../build")
// 生成 package.json
const createPackageJson = name => {
const fileStr = `{
"name": "${name ? name : "pc-vue3-ui"}",
"version": "${version}",
"description": "Vue3组件库",
"main": "${name ? "index.umd.js" : "pc-vue3-ui.umd.js"}",
"module":"${name ? "index.mjs" : "pc-vue3-ui.mjs"}",
"repository": {
"type": "git",
"url": "git+https://github.com/GGXXMM/vue3-ui.git"
},
"keywords": ["vue3", "组件库", "UI"],
"author": "guoxinming",
"license": "ISC"
}
`
// 单个组件 or 全量
const filePath = path.resolve(
outputDir,
name ? `${name}/package.json` : `package.json`
)
fs.outputFile(filePath, fileStr, "utf-8")
}
/** 单组件按需构建 */
const buildSingle = async name => {
await build(
defineConfig({
...baseConfig,
build: {
lib: {
entry: path.resolve(compontsDir, name),
name: "index",
fileName: "index",
formats: ["es", "umd"]
},
rollupOptions,
outDir: path.resolve(outputDir, name)
}
})
)
createPackageJson(name)
}
/** 全量构建 */
const buildAll = async () => {
await build(
defineConfig({
...baseConfig,
build: {
lib: {
entry: compontsDir,
name: "pc-vue3-ui",
fileName: "pc-vue3-ui",
formats: ["es", "umd"]
},
rollupOptions,
outDir: outputDir
}
})
)
createPackageJson()
}
const buildLib = async () => {
await buildAll()
// 按需打包
fs.readdirSync(compontsDir)
.filter(name => {
// 获取组件的目录
const componentDir = path.resolve(compontsDir, name)
const isDir = fs.lstatSync(componentDir).isDirectory()
return isDir && fs.readdirSync(componentDir).includes("index.ts")
})
.forEach(async name => {
await buildSingle(name)
})
}
buildLib()
执行完打包脚本 scripts/build.js,build文件夹下自动编译生成如下文件:
发布 NPM
组件库源码编译打包完成后,我们准备将打包好代码发到 NPM 上,激动人心的时刻即将到来!!我们先来梳理下发布步骤:
-
注册npm账号,前往 www.npmjs.com/ 注册(若已有账号跳过此步骤)
-
设置npm registry源地址(若当前源已是npm可跳过此步骤)
npm config set registry https://registry.npmjs.org
- 账号登录及核对(若已登录并确认账号可跳过此步骤)
# 登录账号
npm login
# 核对账号
who am I
- npm publish 发布
# 此处只想发布打包编译后的文件
npm publish ./build
看到上图信息表示发布成功啦👏👏,到 NPM 官网也可搜索验证:
如果发布操作频繁,我们可以封装一个发布脚本,自动化执行发布,节省时间。脚本代码如下:
publish.sh:
npm config set registry https://registry.npmjs.org
npm login # 登录,如果有 OTP, 邮箱会接收到验证码,输入即可
# 登录成功后,短时间内会保存状态,可以直接
npm publish ./build # 可能会报错提示已存在,升级个版本号再发
# 还原镜像地址
npm config set registry https://registry.npmmirror.com
总结
行文至此,我们已实现了从0-1构建Vue3组件,从概要设计到组件开发,再到单元测试和打包发布的全流程。(Vue3组件库专题完美收官啦!!)剩下的工作就是继续完善组件库,有兴趣参与的小伙伴欢迎到 github 协同开发~~
本专栏文章:
转载自:https://juejin.cn/post/7255514764754894907