前端工程化:从0到1实现Vue3-UI框架那么如何摆脱小打小闹,自己生产一套企业级UI框架? 本文将从0到1实现一
1、背景
日常代码开发过程中,前端er经常需要使用各种开源的UI框架,也会自己封装一些组件使用。那么如何摆脱小打小闹,自己生产一套企业级UI框架?
本文将从0到1实现一个UI框架,给大家提供一个思路。
2、需求列表
3、需求分析
- 先做Button组件,跑通流程。
- 使用VietPress搭建文档界面,编写markdown显示。
- 使用ESLint、Prettier、Husky进行强制性的代码规范
- 使用最新的技术栈:Vue3+Vite+TS+JSX
- 发布npm包
4、架构设计
1)设备环境
设备:Win10
浏览器:Chrome100+ 😀
Node:v20.15.0
2)UI组件
只做Button组件,代码风格模仿Element、Vant。使用方法也类似。如:
import zyUi from "zy-ui-shen/lib/index.js"
import "zy-ui-shen/lib/style/index.css"
const app=createApp(App)
app.use(zyUi)
3)源码管理
代码管理方面有Multirepo、Monorepo两种类型,区别如下:
综合如上 Monorepo VS MultiRepo,中大型项目,多模块项目,更适合用 MonoRepo 方式管理代码,在开发、协作效率、代码一致性方面都能受益。通过 pnpm 来实现(可以切换镜像地址)。
为什么不适用npm/yarn?
npm/yarn 安装依赖时,存在依赖提升,某个项目使用的依赖,并没有在其 package.json 中声明,也可以直接使用,这种现象称之为 “幽灵依赖”;随着项目迭代,这个依赖不再被其他项目使用,不再被安装,使用幽灵依赖的项目,会因为无法找到依赖而报错。使用pnpm完美解决。
4)项目初始化
使用Vite建项目,选择Vue3+TS
pnpm create vite
5)代码规范
使用eslint、prettier进行代码风格管理,选择husky进行git提交前校验(单人开发没必要)。使用husky,需要在.husky目录下新增commit脚本,执行命令即可。
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx --no-install lint-staged
6)单元测试
使用Vitest做单元测试,他的好处
- 同属vite生态,跟vite使用统一配置、解析器、插件
- 支持TS/JSX
7)使用VitePress做文档管理
根据markdown自动生成页面,支持预览。
8)技术栈
TS+TSX+Vite+Vue3+Less,技术栈都是当前较为流行的。
技术准备完成,开始coding!
5、代码开发
1)编写Button组件
组件使用JSX语法开发。相比较Vue,JSX更灵活,更容易理解和维护,也更有逼格。文件名:Button.tsx,代码如下:简单添加了Class、slot、disable属性,可以看出效果。
import { defineComponent } from "vue"
import { buttonProps, ButtonProps } from "./types"
import { createNamespace } from "../../utils/create"
const [name, bem] = createNamespace('button');
export default defineComponent({
name,
props: buttonProps,
setup(props: ButtonProps, { slots }) {
return () => {
const {
tag,
type,
size,
disabled,
} = props;
const defaultSlot = slots.default ? slots.default() : "按钮"
const classes = [
bem([
type,
size,
{
disabled,
},
])
];
return (
<tag
class={classes}
disabled={disabled}
>
{defaultSlot}
</tag>
)
}
}
})
添加index.ts,组件新增withInstall方法,这是按需引用的关键。
import { withInstall } from '../../utils/install';
import _Button from './Button';
export const Button = withInstall(_Button);
export default Button;
declare module 'vue' {
export interface GlobalComponents {
ZYButton: typeof Button;
}
}
样式单独放在style目录。
在style/index.less中引入所有样式文件,作为全引用入口。如果按需加载,引入对应组件样式即可。
组件大功告成,接下来才是重头戏!
2)VitePress
文档项目,可以和组件库放到同一个项目里,这样也便于组件引用。根据需求,文档不仅要展示组件使用方法,还要展示组件的样式效果,这就需要在markdown中直接展示demo。为此我们需要用到以下插件:
- @vitepress-demo-preview/plugin插件:它支持区块内的方式展示demo和示例代码。
- @vitejs/plugin-vue-jsx插件:可以很好的使用TSX。
完善config.js文件之后,在package.json添加启动命令:vitepress dev docs 。直接看效果:
符合预期!其中展示代码直接引用的vue文件
markdown
button.vue
3)打包
使用vite build是最简单的,但这样打出的包,所有CSS搞成一个文件。但我们要想实现Vant、Element那样按需使用组件,如:
import zyUi from "zy-ui-shen/lib/index.js"
import "zy-ui-shen/lib/style/index.css"
const app=createApp(App)
app.use(zyUi)
在这里,引入新的打包工具gulp。值得注意的是,为了避免其他无关紧要的东西被打进去,这里特意制定组件目录。
import delPath from '../utils/delpath';
import { series, parallel, src, dest } from 'gulp';
// componentPath是组件所在根目录
import { pkgPath, componentPath } from '../utils/paths';
import less from 'gulp-less';
import autoprefixer from 'gulp-autoprefixer';
import run from '../utils/run';
//删除zy-ui
export const removeDist = () => {
return delPath(`${pkgPath}/zy-ui`);
};
//打包样式
export const buildStyle = () => {
return src([`${componentPath}/style/**.less`,`${componentPath}/style/**/**.less`])
.pipe(less())
.pipe(autoprefixer())
.pipe(dest(`${pkgPath}/zy-ui/lib/style`))
.pipe(dest(`${pkgPath}/zy-ui/es/style`));
};
//打包组件
export const buildComponent = async () => {
run('pnpm run build', componentPath);
};
export default series(
async () => removeDist(),
parallel(
async () => buildStyle(),
async () => buildComponent()
)
);
执行打包指令:npm run build:zy-ui
打完的包目录如下:
4)发包
Step1:在npm官网,进行注册
Step2:设置npm地址
有些本地npm地址可能改为了镜像地址,此次因为要发布,先改过来。
npm config set registry https://registry.npmjs.org
Step3:登录账号
npm login
Step4:npm publish 发布
注意:包名不能太简单。
npm publish ./zy-ui
zy-ui目录是打好的包目录,包里一定要有package.json和README.md文档。
package.json
{
"name": "zy-ui-shen",
"version": "1.0.0",
"main": "lib/index.js",
"module": "es/index.mjs",
"files": [
"es",
"lib"
],
"keywords": [
"zy-ui-shen",
"vue3组件库"
],
"sideEffects": [
"**/*.css"
],
"author": "六神",
"license": "MIT",
"description": "",
"typings": "lib/index.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/ashenBourne/ui-vue3"
}
}
5)测试一下
Step1:利用Vite新建一个Vue项目
如果你没装vite,先安装一波
pnpm install -D vite
npm create vite my-vue-app -- --template vue
Step2:安装zy-ui-shen
pnpm i zy-ui-shen
此时,在node_modules目录中,zy-ui-shen已完成安装
Step3:引入并使用zy-ui-shen
在main.js中引入
import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
import zyUi from "zy-ui-shen";
import "zy-ui-shen/lib/style/index.css";
let app = createApp(App);
app.use(zyUi);
app.mount("#app");
在App.vue中使用
效果如下:
6、写在最后
至此,整个项目完整跑了下来,我们实现了完全属于自己的UI组件库。完整的代码地址:zy-ui-shen。造这个轮子,目的只是为了了解市面上一般UI框架背后的逻辑,所以没有太精细化。
作为一名从业7年的老前端,一直有种感觉:前端玩的再花,也只是螺蛳壳里做道场。在平时的生产开发中,前端甚至不需要过多了解业务逻辑,也能完成开发任务。这非常可怕,很难向更高处扩展。前不久借调到业务部门,才真正发现和理解业务的背后的逻辑,才理解每一个需求背后,是经过怎样的一种博弈。以后该卷一点更有意义的地方了。
转载自:https://juejin.cn/post/7406235645126213658