@wei_design/web-vue
技术栈
关于技术选型
2022年了,相信对于vite
、vue3
听得不能再多了,对于他们的剖析也多的不能再多了,
如果你还没用上这些,何不造个组件库,一起卷起来…
vue
https://cn.vuejs.org/
这里使用vue3去搭建,其实就是多了一些api,换了写法,选项式api和组合式api的切换了,也可以更丝滑的使用ts要使用vue2的写法也不是不可以,但不推荐
"vue": "^3.2.*"
vite
https://cn.vitejs.dev/
原生esm
打包工具,没用过的刚好可以练练手
"vite": "^3.0.*"
typescript
vue3用ts重写了,性能和体积都更优秀了,2202年了,ts卷起来
"typescript": "^4.*.*"
vitepress
"vitepress": "^1.0.0-alpha.*"
当然,组件库必须得有一个文档库了,这里使用vitepress1.0.0-alpha.*
,虽然还是alpha,但看到UI相信你也会用上他的vite
官网也更新了vitepress1.0.0-alpha.*
项目搭建
Node Version:>=16.0.0
可以选择通过vite
提供模板创建,也可以使用vue-cli
来创建
当然,伟大的项目都是从git init
开始的
1、vite模板创建
https://vitejs.dev/guide/#scaffolding-your-first-vite-project
- npm
npm init vite@latest
- yarn
yarn create vite
选择Vue
并选择使用TypeScript
也可以直接指定对应的模板来初始化
yarn create vite vite-app-vue --template vue-tsc
2、vue cli创建
https://cn.vuejs.org/guide/quick-start.html#with-build-tools
npm init vue@latest
使用官方vue cli
可以提供给你对于TypeScript
、ESLint
和Vitest
之类的可选支持
Vue.js - The Progressive JavaScript Framework
✔ Project name: … web-vue
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit Testing? … No / Yes
✔ Add Cypress for End-to-End testing? … No / Yes
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / Yes
Scaffolding project in /Users/forguo/work/wei-design/web-vue...
Done. Now run:
cd web-vue
npm install
npm run lint
npm run dev
如果为了省事,使用vue-cli
即可,就不用后面再去配置ESLint
、Prettier
eslint + prettier 配置
组件库搭建
关于组件库引用
首先,来说说组件库的引用,众猿周知
使用npm包有两种方式,还有cdn
引入(后面会说怎么使用免费cdn)
1、全量引用
在main.js
中
import { createApp } from 'vue';
import App from './App.vue';
// 完整引入组件库
import WeDesign from '@wei_design/web-vue';
const app = createApp(App);
// 全局安装
app.use(WeDesign).mount('#app');
组件当中
<WeButton :loading="true">按钮组件</WeButton>
2、按需引入
main.js
中
import { createApp } from 'vue';
import App from './App.vue';
// 按需引入
import { Button } from '@wei_design/web-vue';
const app = createApp(App);
app.use(Button).mount('#app');
组件当中
<WeButton :loading="true">按钮组件</WeButton>
要做一个组件库,就得提供这两种引入方式
开始第一个组件
1、组件开发
需要先来添加下sass编译器
pnpm install sass
添加packages/components
文件夹,或mkdir packages/components
,这里用来存放组件库的源码
添加button
文件夹,也就是第一个组件button
组件文件夹可以这样来组织
├── src # 组件源码
│ ├── index.scss # 样式
│ ├── index.vue # 组件
│── index.ts # 组件库导出
index.scss
中添加样式
@import "../../../theme/color.variables";
button {
outline: none;
}
.we-button {
padding: 8px 12px;
overflow: hidden;
border-radius: 6px;
border: 0;
text-align: center;
display: inline-block;
position: relative;
outline: none;
font-weight: 400;
-webkit-appearance: none;
user-select: none;
cursor: pointer;
white-space: nowrap;
transition: all 0.1s linear;
box-sizing: border-box;
}
.we-button-type-default {
background: $primaryColor;
color: $white;
}
.we-button-disabled {
background-color: #f7f7fa;
cursor: not-allowed;
color: $black;
&:focus,
&:hover {
background-color: #f7f7fa;
outline: none;
}
}
index.vue
中添加button
组件代码vue3
及ts
可以提前来浅学一下
<template>
<button :class="[classString]" :disabled="disabled">
<slot></slot>
</button>
</template>
<script lang="ts">
import { defineComponent, PropType } from 'vue'
import './index.scss'
const Props = {
type: {
type: String as PropType<string>, // 转为ts类型string
default: 'default'
},
disabled: {
type: Boolean as PropType<boolean>,
default: false
},
}
export default defineComponent({
name: 'WeButton',
props: Props,
setup(props) {
const classString = [
'we-button',
`we-button-type-${props.type}`,
props.disabled ? 'we-button-disabled' : ''
]
return {
classString
}
}
})
</script>
添加index.ts
组件注册
单个组件的使用,也有局部注册和全局注册
局部注册通过components
来完成
全局注册就得通过App.component(Button.name, Button)
当然,这样页比较麻烦,可以直接提供install
方法,使用的时候通过use
方法来完成注册
import { App } from 'vue'
import Button from './src/index.vue'
Button.install = function (app: App) {
// 组件注册,按需引入
app.component(Button.name, Button)
return app
}
export default Button
2、组件库导出
添加component.ts
,导出所有的组件
/**
* 导出所有组件
*/
import Button from './components/button'
export default [Button]
export { Button }
添加index.ts
,提供组件库全量注册引入及单个组件注册引入
import { App } from 'vue'
import components from './component'
// 所有组件
export * from './component'
// 完整引入组件
const install = function (app: App) {
components.forEach(component => {
app.use(component as unknown as { install: () => any })
})
}
export default {
install
}
也可以添加一些公共的工具及插件到packages
文件夹下
最终的packages
是这样的
├── components/* # 组件源码
│── theme # 样式及主题文件
│── utils # 工具及插件
│── component.ts # 所有的组件都在这里来管理
│── index.ts # 导出单个组件或者整个组件库
3、调试
在src/main.js
中引入组件库来测试组件的效果
import { createApp } from 'vue'
import App from './App.vue'
// 完整引入组件库
import WeDesign from '../packages/index' // 可以配置alias
const app = createApp(App)
app.use(WeDesign).mount('#app')
app.vue
当中使用
<template>
<div class="wei-app">
<h1>wei-design</h1>
<hr>
<div>
<we-button>按钮组件</we-button>
<we-button style="margin-left: 12px" disabled>按钮组件</we-button>
</div>
</div>
</template>
run一下,看下效果,组件库的雏形就好了
规范化
Git提交规范
组件库发布
组件库开发好了,就得发布npm
,别人就可以来安装使用了
创建并发布一个npm包
1、打包配置
vite库模式配置
编辑vite.config.ts
// [vite库模式配置](https://cn.vitejs.dev/guide/build.html#library-mode)
build: {
outDir: 'lib',
lib: {
entry: resolve(__dirname, './packages/index.ts'),
name: 'WebVue',
fileName: 'web-vue'
},
rollupOptions: {
// 确保外部化处理那些你不想打包进库的依赖
external: ['vue'],
output: {
// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
globals: {
vue: 'Vue'
}
}
}
},
配置好之后,执行npm run build
完成打包
2、package配置
主要需要修改以下几点
package.json中的browser,module,main解析
{
"name": "@wei_design/web-vue", // 包名,可以直接是包名,也可以@wei_design[组织]/web-vue[包名]
"private": false, // 是否私有包,发布公共的需要设置false
"version": "1.0.0", // 版本,每次发布都需要修改
"author": "wforguo@qq.com",
"description": "Wei Design - A Vue.js 3 UI library, @wei_design/web-vue", // 包的简述
"keywords": [
"@wei_design/web-vue" // 关键词
],
"homepage": "https://wei-design.github.io/web-vue/",
"repository": {
"type": "git",
"url": "https://github.com/wei-design/web-vue.git"
},
// 主要上传哪些文件或者文件夹到npm
"files": [
"lib/*",
"packages/*",
"Readme.md",
"package.json"
],
// 入口文件【注意文件后缀】
"main": "./lib/web-vue.umd.js",
"module": "./lib/web-vue.mjs",
"exports": {
".": {
"import": "./lib/web-vue.mjs",
"require": "./lib/web-vue.umd.js"
},
// 这里css页需要导出,否则导入css会报错
"./lib/style.css": "./lib/style.css"
},
"engines": {
"node": ">=16.0.0"
}
}
3、npm发布
如何发布自己的 npm 包
首先去注册一个npm账号
在电脑terminal中登录npm,可以使用npm whoami
先来查看npm
登录状态
npm login
- 私有发布
npm publish 命令执行,默认是进行私有发布
scoped的包私有发布时需要收费
- 公共发布
发布成功之后,邮箱也会收到提醒npm publish --access public
好了,到这里,你的组件库就已经成功上线了
接下来就是去使用看看有没有什么问题
import { createApp } from 'vue';
import App from './App.vue';
// 完整引入组件库
import WeDesign from '@wei_design/web-vue';
const app = createApp(App);
// 全局安装
app.use(WeDesign).mount('#app');
使用CDN
Free CDN for Open Source
两个都是开源免费的CDN,只要你发布了npm,替换下面包名为就可以去使用了
1、unpkg
资源浏览 https://unpkg.com/@wei_design/web-vue/
<link
rel="stylesheet"
href="//unpkg.com/@wei_design/web-vue/lib/style.css"
/>
<script src="//unpkg.com/@wei_design/web-vue"></script>
2、jsdelivr
资源浏览 https://cdn.jsdelivr.net/npm/@wei_design/web-vue/
<link
rel="stylesheet"
href="//cdn.jsdelivr.net/npm/@wei_design/web-vue/lib/style.css"
/>
<script src="//cdn.jsdelivr.net/npm/@wei_design/web-vue"></script>
问题及解决
列举了一些自己遇到的问题,希望不会帮到你
如果有遇到问题,不知道怎么解决,可以到github上@wei_design/web-vue对比代码看下是否哪里有不对的地方
- 【组件库发布】npm publish 时提示需要升级TLS 1.2的解决方案
看看registry是否是https的,否则需要切换到https
npm config set registry https://registry.npmjs.org
- 【组件库npm使用】副作用导致打包后引入npm中的css报错
- 【文档库】运行报错报错:TypeError: Invalid value used as weak map key
md中有无法解析的标签导致
- 【组件库npm使用】引入
lib/style.css
导致ModuleNotFound
错误
修改exports
导出条件语法,新增./lib/style.css
"exports": {
".": {
"import": "./lib/web-vue.es.js",
"require": "./lib/web-vue.umd.js"
},
"./lib/style.css": "./lib/style.css"
}
- 【文档库】vitepress打包报错
To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
解决办法,修改vite.config.ts
中lib配置
build {
lib: {
entry: resolve(__dirname, './packages/index.ts'),
name: 'WebVue',
fileName: 'web-vue'
},
}
修改package.json
"main": "./lib/web-vue.umd.js",
"module": "./lib/web-vue.mjs",
"exports": {
".": {
"import": "./lib/web-vue.mjs",
"require": "./lib/web-vue.umd.js"
},
"./lib/style.css": "./lib/style.css"
},
文档库搭建
正在努力加载中….
都到这了,点个赞再走吧
GitHub奉上…