Vue3 + Vite 构建组件库的流程
本文教你如何用 Vue + Vite,一步一步构建一个组件库并发布到 npm 的整体流程
1. 通过 vite 命令创建一个基本的项目结构(这里选用 vue + ts 的项目)
-
npm create vite@latest
2. 在项目中创建一个 lib 目录,用于存放组件库所要编写的组件
3. 我们先在 lib 中编写组件库的第一个组件,用于这次组件库的搭建的组件 - 这里只通过创建一个简单的按钮 button 组件来作为测试
-
<!-- lib/components/HButton.vue --> <script setup lang="ts"> import { ref } from 'vue'; defineProps<{ title: string }>() const count = ref(0) </script> <template> <button class="h-button" @click="count++">{{ title }} : {{ count }}</button> </template> <style scoped> .h-button { background-color: #409eff; color: white; padding: 0 16px; height: 34px; line-height: 34px; border-radius: 4px; border: 0px; cursor: pointer; } .h-button:hover { background-color: #66b1ff; } </style>
4. 我们可以先在 App.vue 中引入该组件,来测试一下该组件
-
<script setup lang="ts"> import HButton from "../lib/components/HButton.vue" </script> <template> <h1>app</h1> <hr> <HButton title="小孔" /> </template>
5. 当组件测试没有问题后,接下来我们需要在 vite.config.ts 配置文件中,配置项目打包为一个 lib 库模式
-
// vite.config.ts : 项目初始配置 import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' export default defineConfig({ plugins: [vue()], })
-
// // vite.config.ts : 配置 build 打包模式为 lib 库模式 → 下面对应的配置也可以直接在 vite 官方文档中找到对应的示例 import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { resolve } from "path" export default defineConfig({ plugins: [vue()], build: { lib: { entry: resolve(__dirname, 'lib/main.ts'), // -- 配置打包的库的入口文件 name: 'my-lib-test', fileName: 'my-lib-test' // -- 配置打包的文件名 }, rollupOptions: { // -- 配置你不需要打包进库中的依赖库(因为该组件库是在 vue 项目中的,所以使用的项目需要本身就有 vue 依赖库了,所以我们在这里不需要打包进组件库中) -- 如果你还有其它的依赖也不想打包进依赖库中,同理 external: ['vue'], } } })
-
注意: - 我们将上面的配置好后,我们会发现他的有些代码报错了
-
这是因为 vite 创建的项目,默认是没有对应 node 的相关类型的,而 path 与 __dirname 是 node 中的东西
-
解决该问题,我们只需要下载对应的 node 类型库就行了 →
npm i @types/node
6. 在对应的 lib 库的入口文件 main.ts 中引入我们所写好的 HButton 组件,并导出我们需要导出的组件
-
// lib/main.ts // -- 引入我们写好的组件并在 main.ts 入口文件中将其导出 → 使其在打包中可以将该组件构建进去 export { default as HButtom } from "./components/HButton.vue"
7. 我们可以先通过 npm run build 来打包一下,来看一下效果
-
上面打包后的
dist
目录中还有两个先问题,一个是 vite 默认会将public
中的内容直接复制到对应的打包目录中,一个是没有将对应的类型声明构建进去-
第一个问题: 我们可以通过在 build 中将 copyPublicDir 配置为 false → 表示构建时不对 public 中的内容进行复制
-
// vite.config.ts export default defineConfig({ build: { copyPublicDir: false, // ... } })
-
-
第二个问题: 我们可以通过在 vite 中配置 vite-plugin-dts 插件,该插件可以使在库模式下,自动根据源文件生成对应的类型声明文件(🔺因为需要处理的东西比较多,在下面进行介绍 ↓)
-
8. 通过 vite-plugin-dts 来生成对应的类型文件
-
安装: -
npm i vite-plugin-dts -D
-
配置:
-
// vite.config.ts import dts from 'vite-plugin-dts' export default defineConfig({ plugins: [ vue(), dts({ // -- 配置 vite-plugin-dts 插件 rollupTypes: true, // -- 是否将说有的类型声明,合并到一个文件中 tsconfigPath: "./tsconfig.json" // -- 指定对应的 tsconfig 文件,会根据该配置文件中的 include 配置生成对应的类型声明 }) ], // ... })
-
-
如上图,我们会发现一个问题,如果我们配置好对应的 dts 插件后,重新构建时,会出现一些错误,且所生成的类型文件也是存在问题 → 🔺这是因为 dts 中的 tsconfigPath 配置的问题
-
因为 tsconfigPath 我们配置的是 tsconfig.json 中的 include 中不是我们想要包含的文件
-
🔺我们可以创建一个专用于打包的 ts 配置文件(tsconfig.build.json),并将 dts 插件中的 tsconfigPath 配置该 ts 配置文件
-
// tsconfig.build.json { "extends": "./tsconfig.json", // -- 除了 include 配置外,其它所有配置都继承于原本的 tsconfig.json 配置文件 "include": [ // -- 配置所要包含想要包含的目录(如下就表示 lib 目录下的多有内容) "lib", ] }
-
export default defineConfig({ plugins: [ vue(), dts({ rollupTypes: true, tsconfigPath: "./tsconfig.build.json" // -- 替换成 tsconfig.build.json 配置文件 }) ] })
-
-
此时,我们在通过 npm run build 时,就不会出现对应的报错,且对应打包的库也能生成正常对应的类型声明文件了
9. 上面还可以做一个小优化,可以通过上图看到,组件中的样式它是打包到一个单独的 css 文件中的,并且默认时不会自动在对应打包的 js 中引入该样式
-
也就是说,我们在使用该组件时需要先引入对应的该库中的 css 文件(如在对应项目 main.ts 项目入口中引入)
-
我们也可以通过 "vite-plugin-libcss" 插件来帮助我们自动引入对应的样式文件,该插件可以自动的将对应 css 通过 import 导入到对应捆绑的 js 文件中
-
安装:
npm i vite-plugin-libcss -D
-
配置:
-
// vite.config.ts : 在 vite 中配置对应插件 import libCss from 'vite-plugin-libcss'; export default defineConfig({ plugins: [ // .. libCss() ], // .. })
-
-
此时,我们打包后查看对应的 js 文件,就会发现它会自动的将对应的 css 进行注入,所以我们现在就可以直接在项目中引入对应的 js 文件中的内容来使用即可
-
10. 现在,我们在 App.vue 组件中导入对应打包后的 dist 目录下的文件中的组件,来进行使用与测试
-
<!-- src/App.vue --> <script setup lang="ts"> import { HButtom } from "../dist/my-lib-test" // -- 引入打包后的库的组件 </script> <template> <h1>app</h1> <hr> <HButtom title="小孔" /> </template>
-
使用起来也一切正常后,接下来我们就可以将该库发布到 npm 上了
11. 现在,发布 npm 包还需要再 package.json 中做一些简单配置,具体如下
-
// package.json { "name": "lib-test", // -- 必填: 库名,必须是唯一的,可以先上 npm 搜索,看是否已经存在该库了(如果已经存在,需要更换名称) "version": "0.0.1", // -- 必填: 版本号(如果更新包内容,此项也必须比前面的版本高) "private": false, // -- 此项默认为 true,需要将其配置成 false 或删除该配置项 "type": "module", "main": "./dist/my-lib-test。umd.js", // -- 指定包的入口文件(通过 require 引入包时,加载的文件 ) "module": "./dist/my-lib-test.js", // -- 指定包的入口文件(通过 esmodule 引入时,加载的文件) "types": "./dist/my-lib-test.d.ts", // -- 指定 ts 类型声明文件 "files": [ // -- 指定发布包时,所包含的文件和目录 "dist" ], "description": "测试 lib 组件库", // -- 包描述 "scripts": { "dev": "vite", "build": "vue-tsc -b && vite build", "preview": "vite preview" }, "peerDependencies": { // -- 我们可以该库需要依赖的,放到 peerDependencies 配置项中(用于提示用户与再npm中会有对应的显示) "vue": "^3.5.12" }, "devDependencies": { "@vitejs/plugin-vue": "^5.1.4", "typescript": "~5.6.2", "vite": "^5.4.10", "vite-plugin-libcss": "^1.1.1", "vue-tsc": "^2.1.8", "@types/node": "^22.9.0", "vite-plugin-dts": "^4.3.0" } }
12. 最后,我们只需要再命令行中执行对应的命令进行发布即可 - tip: 需要有对应的 npm 账号 & 在下面命令操作时,有时候经常会因为网络问题登录或发布失败,可以多尝试几遍
-
🔺在执行下面的命令前,先提几个注意的点:
-
(1) npm 的源必须为官方源,如果先前切换成淘宝的源或其它的源后,需要先将 npm 切换会原来的官方源
-
npm config set registry https://registry.npmjs.org/
-
-
(2) 在登录会发布过程中,因为 npm 源是国外的,所以可能会经常存在登录失败或上传失败的问题,可能是网络的问题,可以多尝试几遍
-
(3) 当包重名时也会上传失败,所以出错时可以留意一下对应的信息(如下错误示例 ↓)
-
-
1.需要在命令行中通过 "npm login" 命令来登录 npm
-
2. 登录成功后,在通过 "npm publish" 命令来进行上传即可
-
此时,该包我们就成功发布到 npm 中了
-tip: 需要注意包重名的问题,在上面的注意示例中有图例
13. 此时我们就可以通过 npm 来下载并使用我们的组件库了,下面就为一个基本的使用示例(可跳过不看,因为不是重点) - tip: 此测试库我后续会删除,这里只是演示与测试是否能够正常工作
-
安装:
npm i lib-test-kxh
-
再 App.vue 中引入并使用
-
<script setup lang="ts"> import { HButtom } from "lib-test-kxh" </script> <template> <h1>App</h1> <hr> <HButtom title="小孔" /> </template>
-