为什么需要一个业务组件库
因为我们项目为 polyrepo,众多项目分散在各个仓库中。整个后台系统项目是微前端架构, 应该各个子系统之间没啥关系。但从项目整体角度出发,对于 ui 有一致性的要求,因此难免有部分组件需要复用。
快速开始
采用成熟的脚手架快速搭建一个库。
team-innovation/vue-sfc-rollup: Quickly generate redistributable Vue components with Rollup
运行命令 npx vue-sfc-rollup ,按照提示,选择搭建一个 library。
踩坑
编译 less style
如果 vue sfc 文件中使用了 less 或者其他 css 扩展语言,需要安装对应的包。在我的项目中,我使用了 less , 那么需要运行 npm i -D less 安装 less
TypeError: Cannot read property 'NormalModule' of undefined
主要原因是我安装了不匹配的 less 和 less-loader , 然后运行vue-cli-service serve dev/serve.ts 报错。
搜索了一圈无果,vue.js - TypeError: Cannot read property 'NormalModule' of undefined - Stack Overflow ,试了这个方法也没用
错误的依赖:
"less": "^4.0.0",
"less-loader": "^8.0.0",
修改成较低版本就能跑了,修改如下:
"less": "^3.0.0",
"less-loader": "^5.0.0",
编译前把之前的产物删掉
这么做可以保证编译产物清晰,不会这次编译产物和上次编译产物混在一起,造成混乱。
在 package.json 的 scripts 文件中,添加
"prebuild": "rimraf ./dist"
运行 yarn serve 报错。 cant find @/entry.esm
主要是 ts 没有解析到这个路径,需要安装 "@vue/cli-plugin-typescript": "^4.5.15" ,然后 在 tsconfig.json 配置一下 paths
"paths": {
"@/*": ["./src/*"]
}
eslint and prettier
eslint and prettier config
config file inspired from arco-design/arco-design-vue: A Vue.js 3 UI Library based on Arco Design
提交时自动 format
- typicode/husky: Git hooks made easy 🐶 woof!
- okonet/lint-staged: 🚫💩 — Run linters on git staged files
随着 husky 版本升级,配置方式发生了一点点变化。
- Edit package.json > prepare script and run it once:
npm set-script prepare "husky install"
npm run prepare
- Add a hook:
npx husky add .husky/pre-commit "npm test"
git add .husky/pre-commit
- In .husky/pre-commit
#!/usr/bin/env sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged
文档
组件库搭建好了,需要搭配一个文档,看似选择很多,但是大多对 vue3 支持不是很好。看了一下文档生成工具:
- @vuese/cli | Vuese : not support vue3
- Introduction to Storybook
- vue-styleguidist/vue-styleguidist: Created from react styleguidist for Vue Components with a living style guide : version 4.44.0 support vue3
- vuepress/vuepress-next: Repo for VuePress 2
最后选择了成熟,支持 vue3 ,且能灵活自定义的 @storybook/vue3
引入库的全局样式
因为我的组件库是基于 ant-design-vue 的二次封装,因此在用到 ant-design-vue 组件的地方,需要引入 ant-design-vue 对应组件的样式。如果每个 story 都要引入样式的话就太麻烦了,于是查文档可得,在 .storybook/preview.js 里引入库的样式即可
import 'ant-design-vue/dist/antd.css';
export const parameters = {
/* some code */
};
处理 less
查文档可得,在 .storybook/main.js 里面添加处理 less 文件的配置
module.exports = {
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
addons: ['@storybook/addon-links', '@storybook/addon-essentials'],
framework: '@storybook/vue3',
webpackFinal: async (config, { configType }) => {
config.module.rules.push({
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader'],
});
return config;
},
};
如何编写 story
参考文档,感觉比较好的方式是写一个 template,然后基于模板新建 story,修改参数即可
const Template = (args) => ({
components: { ButtonGroup },
setup() {
return { args };
},
template: '<ButtonGroup v-bind="args" />',
});
how to write docs
可以参考 ant design 的文档结构,下拉菜单 Dropdown - Ant Design
# 英文 + 中文
一句话描述你的组件作用
## 何时使用
## 代码演示
## API
收获
实时开发
vue-sfc-rollup 提供了便捷开发组件的方式。 巧妙了利用了 esm,直接起了一个 vue 服务。示例代码如下:
// serve.ts
import { createApp } from 'vue';
import Sandbox from './sandbox.vue';
// To register individual components where they are used (serve.vue) instead of using the
// library as a whole, comment/remove this import and it's corresponding "app.use" call
import Components from '@/entry.esm';
const app = createApp(Sandbox);
app.use(Components);
app.mount('#app');
// @/entry/esm
import { App, Plugin } from 'vue';
// Import vue components
import * as components from './components/index';
// install function executed by Vue.use()
const install: Exclude<Plugin['install'], undefined> = function installTtComponents(app: App) {
Object.entries(components).forEach(([componentName, component]) => {
app.component(componentName, component);
});
};
// Create module definition for Vue.use()
export default install;
// To allow individual component use, export components
// each can be registered via Vue.component()
export * from './components/index';
如何处理 peerDependence
由于 npm 版本 3 到 6 的版本,不会自动安装 peerDependence 中的依赖。但是开发的时候又需要用到这些包,那怎么办呢,最后采用的骚操作是,把 peerDependence 中的包放在 devDependence 中,再安装一遍。
当然,如果你觉得这种做法比较怪异,可以使用 npm 版本为 7 的版本,该版本会默认安装 peerDependence 中的依赖
另外,peerDependence 中的依赖也不需要放在编译产物中,因此,我们可以在 rollup.config.js 中指定 external,防止将一些包打进产物里。