简介
本文主要讲述如何使用 Vite
+ Vue3.x
+ Typescript
从零搭建组件库。
仓库地址 - github,欢迎使用和点亮小星星。
初始化项目
通过 vue3-base-project 快速搭建项目,详细过程可看之前的文章 从零搭建Vue3.x项目工程环境
调整目录结构
增加 examples
文件夹
用于本地开发时预览使用。
增加 packages
文件夹
用于放置具体封装的组件。
修改 vite.config.json
配置
export default defineConfig({
base: './',
root: join(__dirname, '../examples'),
resolve: {
alias: {
'@': resolve(__dirname, '../'),
'@packages': resolve(__dirname, '../packages'),
'@examples': resolve(__dirname, '../examples'),
'@yui': resolve(__dirname, '../packages'),
},
},
});
编写组件
单个组件目录结构
在 packages/components
目录下创建一个 FullScreenIcon
组件,结构如下
├── FullScreenIcon
│ ├── index.ts
│ └── src
│ ├── index.less
│ └── index.vue
具体代码如下
编写 packages/components/FullScreenIcon/src/index.vue
文件
<script lang="tsx">
import { defineComponent } from 'vue';
import { FullScreen } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import screenfull from 'screenfull';
export default defineComponent({
name: 'FullScreenIcon',
components: {
FullScreen,
},
setup() {
// 全屏
const onFullScreen = () => {
if (screenfull.isEnabled) {
screenfull.toggle();
} else {
ElMessage.warning({
message: '抱歉,当前浏览器不支持该全屏功能,可尝试使用F11触发全屏',
type: 'warning',
});
}
};
return () => {
return (
<el-icon onClick={onFullScreen}>
<full-screen />
</el-icon>
);
};
},
});
</script>
<style lang="less">
@import url('./index.less');
</style>
编写公共install
方法packages/utils/install.ts
import type { App, Plugin } from 'vue';
export const install = <T>(main: T) => {
(main as T & Plugin).install = (Vue: App) => {
// @ts-ignore
Vue.component(main.name, main);
};
return main;
};
编写组件导出 packages/components/FullScreenIcon/index.ts
import { install } from '@yui/utils/install';
import FullScreenIcon from './src/index.vue';
export const YFullScreenIcon = install(FullScreenIcon);
export default YFullScreenIcon;
export * from './src/index.vue';
导出所有组件
新建并编写 packages/index.ts
文件
import components, { ProTable, FullScreenIcon } from './components';
import type { App } from 'vue';
const pkg = require('../package.json');
interface OptsType {}
/**
* 全局注册使用
* @param Vue Vue
* @param opts 配置项参数
*/
const install = (Vue: App, opts?: OptsType) => {
// @ts-ignore
if (install.installed) return;
Object.keys(components).forEach((key: string) => {
Vue.component(key, components[key]);
});
};
// script标签引入
// @ts-ignore
if (typeof window !== 'undefined' && window.Vue) {
// @ts-ignore
install(window.Vue);
}
export { ProTable, FullScreenIcon };
export default {
version: pkg.version,
install,
};
打包组件库
编写打包配置
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';
import Components from 'unplugin-vue-components/vite';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
import vueJsx from '@vitejs/plugin-vue-jsx';
import dts from 'vite-plugin-dts';
const pkg = require('../package.json');
export default defineConfig({
build: {
outDir: 'lib',
minify: true,
lib: {
name: 'yoo-ui-pro',
entry: resolve(__dirname, '../packages/index.ts'),
// formats: ['es', 'cjs', 'umd'],
formats: ['es', 'umd'],
fileName: (format) => `${pkg.name}.${format}.js`,
},
rollupOptions: {
external: ['vue', 'vue-router'],
input: [resolve(__dirname, '../packages/index.ts')],
output: {
globals: {
vue: 'Vue',
},
},
},
},
resolve: {
alias: {
'@yui': resolve(__dirname, '../packages'),
},
},
plugins: [
vue(),
vueJsx(),
Components({
resolvers: [ElementPlusResolver()],
directoryAsNamespace: true,
}),
dts({
entryRoot: resolve(__dirname, '../packages'),
}),
],
});
修改 package.json
{
"name": "yoo-ui-pro",
"version": "0.20.0",
"keywords": [
"component library",
"ui",
"vue",
"yoo-ui"
],
"main": "lib/yoo-ui-pro.umd.js",
"module": "lib/yoo-ui-pro.es.js",
"exports": {
".": {
"require": "./lib/yoo-ui-pro.umd.js",
"import": "./lib/yoo-ui-pro.es.js",
"types": "./lib/index.d.ts"
},
"./*": "./*"
},
"types": "lib/index.d.ts",
"files": [
"lib",
"README",
"LICENSE",
"CHANGELOG.md"
],
"scripts": {
"dev": "vite -c ./build/dev.config.ts",
"build": "vue-tsc --noEmit && vite build",
"build:lib": "vite build -c ./build/lib.build.ts",
"serve": "vite preview",
"lint": "eslint . --ext .js,.ts,.tsx,.vue --ignore-path .eslintignore",
"prepare": "husky install",
"lint:style": "stylelint "src/**/*.(less|css)" --customSyntax postcss-less",
"prepublishOnly": "npm run build:lib"
}
}
执行打包
# 执行命令
npm run build:lib
# 成功后会在根目录生成 lib 文件夹,结构如下
.
├── components
│ ├── FullScreenIcon
│ │ ├── index.d.ts
│ │ └── src
│ │ └── index.vue.d.ts
│ └── index.d.ts
├── favicon.ico
├── index.d.ts
├── style.css
├── utils
│ └── install.d.ts
├── yoo-ui-pro.es.js
└── yoo-ui-pro.umd.js
发布到npm
注册npm账号
登陆
npm login
发布包
npm publish
总结
到此讲完了如何搭建属于自己的组件库的过程,目前组件文档还是单纯的Markdown
进行编写记录,后续将会增加 vitepress
生成组件库文档。
本文有错误的地方欢迎大家指正哈,谢谢大家的支持!