先使用vite 搭建基础版本脚手架这里不做讲解、由于vite初始化什么都没有安装、我采用了自己改造过的脚手架
详情见GitHub 内置
vue-router、commitlint、stylelint、eslint、prettier、unplugin-vue-components、unplugin-auto-import、lint-staged、sentry、pinia、husky...
基本上可以满足团队日常开发需求。
😅言归正传、生成目录大概是这样的
├── README.md
├── commitlint.config.cjs
├── index.html
├── package.json
├── pnpm-lock.yaml
├── public
│ ├── version.txt
│ └── vite.svg
├── src
│ ├── App.vue
│ ├── api
│ │ └── index.ts
│ ├── assets
│ ├── auto-imports.d.ts
│ ├── components
│ ├── components.d.ts
│ ├── global.d.ts
│ ├── hooks
│ ├── intercept.ts
│ ├── main.ts
│ ├── router
│ ├── store
│ ├── utils
│ ├── views
│ ├── vite-env.d.ts
│ └── workers
│ ├── versionCheckWorker.ts
│ └── worker.ts
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
一系列的修改操作
-
修改
src
为
packages
,删除
views
目录
-
修改
alias
把所有和
src
相关的别名路径修改为
components
、修改目录为
vite.config.ts
、
tsconfig.json
// vite.config.ts
alias: [
{
find: "@",
replacement: resolve(__dirname, "../packages"),
},
],
// tsconfig.json
{
...
"paths": {
"@/*": [
"packages/*"
],
},
...
}
-
-
修改index.html中
script
标签中
src
路径为
/packages/main.ts
-
packages
下新建文件夹
theme-chalk
后续用来存放样式
修改后的目录结构
├── README.md
├── commitlint.config.cjs
├── index.html
├── package.json
├── pnpm-lock.yaml
├── public
│ ├── version.txt
│ └── vite.svg
├── packages
│ ├── App.vue
│ ├── api
│ ├── assets
│ ├── auto-imports.d.ts
│ ├── components
│ ├── components.d.ts
│ ├── global.d.ts
│ ├── hooks
│ ├── intercept.ts
│ ├── main.ts
│ ├── router
│ ├── store
│ ├── utils
│ └── vite-env.d.ts
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
后续就可以在
components
文件夹下开发组件了,查看组件的话直接在
router
上配置路径即可
敲黑板
:每个组件必须设置
name
,不然后续全局注册会有问题
components
整体格式如下
├── components
├── button
│ ├──Button.vue
│ └──index.ts
└──index.ts
相关代码如下
-测试按钮-6
defineOptions({
name: "BqButton",
});
@import "@theme-chalk/button.scss";
// index.ts
import Button from "./Button.vue";
import { withInstall } from "../../utils/tool";
export const BqButton = withInstall(Button);
export default BqButton;
withInstall
相关方法如下、主要是为了全局注册
import type { App } from "vue";
export const withInstall = (comp: T) => {
(comp as Record).install = (app: App) => {
const compName = comp.name;
if (!compName) return;
app.component(compName, comp);
};
return comp;
};
// 最外层index.ts
export * from "./button";
这时候我们的组件基本就写好了,查看组件只需要在
router
下配置路径即可
{
path: "/",
name: "button",
meta: {
title: "login",
},
component: () => import(/* webpackChunkName: "button" */ "@/components/button/Button.vue"),
},
打包配置
先给大家看配置、再给大家讲为什么
// vite.config.ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import { resolve } from "path";
import { pluginsConfig, resolveConfig } from "./scripts/preview";
import dts from "vite-plugin-dts";
export default defineConfig(() => {
return {
build: {
outDir: "build",
cssCodeSplit: true,
rollupOptions: {
external: ["three", "@ant-design/icons-vue", "ant-design-vue", "unplugin-vue-components", "unplugin-auto-import", "vue"],
output: [
{
format: "es",
entryFileNames: "[name].js",
exports: "named",
name: "BqDesign",
dir: "./build/dist",
},
{
format: "es",
entryFileNames: "[name].js",
exports: "named",
preserveModules: true,
preserveModulesRoot: "packages",
dir: "./build/es",
},
{
format: "cjs",
entryFileNames: "[name].js",
exports: "named",
preserveModules: true,
preserveModulesRoot: "packages",
dir: "./build/lib",
},
],
},
lib: {
entry: resolve(__dirname, "./packages/index.ts"),
name: "BqDesign",
fileName: (format) => `bq-design.${format}.js`,
formats: ["es", "cjs"],
},
},
plugins: [
vue(),
dts({
tsconfigPath: "./tsconfig.prod.json",
outDir: "build/lib",
}),
dts({
tsconfigPath: "./tsconfig.prod.json",
outDir: "build/es",
}),
...pluginsConfig,
],
resolve: resolveConfig,
};
});
一点一点给大家捋一下为什么这么写
1、为什么
output
需要这样配置
首先按照官网给的示例配置并执行
打包后,有问题吗?没问题。但就是有点奇怪,因为我们打包后结构是这样的
└── dist
├── index.js
└── style.css
毕竟我们都是见过世面的🤓,为什么我们打包出来的和
ant-design-vue
、
ElementPlus
差距这么大,
其实小编在做这个事情的时候也看了这些优秀的开源组件库、毕竟学习的过程就是先
模仿
后
创造
大概看了一下
ElementPlus
是基于vite开发的,
ant-design-vue
还是webpack、那我们先看一下
ElementPlus
打包后的结构大概如下
└── build
├── dist
├── es
├── lib
├── README.md
└── package.json
很明显他输出了三个包(说明我们在output中也需要配置3个输出文件)、首先
es
文件夹用来兼容
esm
语法、
lib
文件夹兼容
commentJs
、
dist
也是esm语法
他的css是打包在一个文件
里的主要是为了全局引入css,配置好后大概是这个样子
output: [
{
format: "es",
entryFileNames: "[name].js",
dir: "./build/dist",
},
{
format: "es",
entryFileNames: "[name].js",
dir: "./build/es",
},
{
format: "cjs",
entryFileNames: "[name].js",
dir: "./build/lib",
},
],
之后我们执行打包脚步
pnpm run build
不报错的情况下打包出来应该已经是有三个文件了,但好像
js
和
css
还是在一起,怎么办?当然是看文档了🤑
原来如此、配置后执行打包命令,果然没问题
2、为什么
cssCodeSplit
是要改为
true
?
因为在
vite
在
lib
模式下
cssCodeSplit
默认是
false
,其实官方有说明,可只在英文文档做了说明🥲
没注意到的打包后所有组件css都在一个文件、后续就没有办法实现我们的按需引入了
3、如何打包出ts类型标注
使用
pnpm
下载
vite-plugin-dts
该插件
pnpm add vite-plugin-dts -D
由于我们在
lib
和
es
库里都需要打包ts,所以需要配置两个dts,代码如下
dts({
tsconfigPath: "./tsconfig.prod.json",
outDir: "build/lib",
}),
dts({
tsconfigPath: "./tsconfig.prod.json",
outDir: "build/es",
}),
tsconfigPath,需要单独引入一个新的tsconfig配置、主要是因为我们打包的include和exclude配置和实际开发中还是有一定区别。并且include配置有问题会导致打包出的类型没有放在实际文件夹下。
新建了一个tsconfig.prod.json文件,代码如下
{
"extends": "./tsconfig.json",
"include": [
"packages/**/*.vue",
"packages/**/*.d.ts",
"packages/**/*.ts",
],
"exclude": [
"./packages/main.ts",
"node_modules",
"./packages/router/*"
]
}
走到这里其实我们的组件已经小有所成了
开发文档
一个好的组件离不开一个优秀的文档、这里我推荐大家使用
VitePress
,相对于市面上其他的文档生成工具
VitePress
拥有着强大的生态环境和相对稳定的版本,文档地址,根据文档操作,之后会在最外层目录下生成一个docs文件,里面就可以快乐的写我们的文档了,这里就不做演示了。
关于 unplugin-vue-components 自动引入
const BqDesignResolver = () => {
return {
type: "component" as const,
resolve: (name) => {
if (name.startsWith("Bq")) {
const pathName = name.slice(2).toLowerCase();
return {
importName: name,
from: "bq-design",
path: `bq-design/es/components/${pathName}/index.js`,