一、基础框架的建立
1、使用vue-cli脚手架创建一个基础的vue3.x+ts项目
2、项目目录结构整理
2.1、修改src目录为examples
examples目录作为所有示例页面的文件入口目录,同时清理文件夹中由vue-cli默认添加的一些无用的示例文件,
由于修改了原有的src目录,所以同时需要对vue.config.js进行修改,使得脚手架能够正确的启动项目:
module.exports = {
pages: {
examples: {
// page 的入口
entry: 'examples/main.ts',
// 模板来源
template: 'public/index.html',
// 在 dist/index.html 的输出
filename: 'index.html',
// 当使用 title 选项时,
// template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
title: 'Examples'
}
}
}
2.2、创建packages目录
packages目录包含组件库中所有的组件以及入口等
2.3、创建typings目录
在项目根路径下创建typing目录,并且将examples目录下的shims-vue.d.ts文件移动到当前目录下。
2.4、修改tsconfig.json文件
修改tsconfig.json文件中的include字段,将修改后的examples目录和packages目录包含在其中。同时typings目录也需要被添加到该配置中。
{
"include": [
"examples/**/*.ts",
"examples/**/*.tsx",
"examples/**/*.vue",
"packages/**/*.ts",
"packages/**/*.tsx",
"packages/**/*.vue",
"typings/**/*.ts"
]
}
2.5、添加一些风格规范和样式规范的配置文件
这个地方根据团队编码风格或个人编码风格设置,不作过多的赘述。
小结:
修改后整个项目目录结构大致如下:
.
├── examples
│ ├── App.vue
│ └── main.ts
├── packages
│ ├── index.ts
├── public
│ ├── favicon.ico
│ └── index.html
├── typings
│ └── shims-vue.d.ts
├── README.md
├── babel.config.js
├── tsconfig.json
├── package.json
└── vue.config.js
二、组件的创建
1、组件A
在packages目录下创建目录comp-a并且在该文件夹下创建src/comp-a.vue文件和index.ts文件
comp-a.vue文件代码如下
<template>
<div style="width: 200px; background-color: red">comp-a</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
name: 'CompA'
})
</script>
index.ts作为组件的入口,目的是为了导出组件并且添加install方法
import { App } from 'vue'
import CompA from './src/comp-a.vue'
// 为组件添加注册方法
CompA.install = (app: App): void => {
app.component(CompA.name, CompA)
}
export default CompA
2、组件B
组件B的创建与组件A同理,不做过多赘述,只展示代码
comp-b.vue
<template>
<div style="width: 200px; background-color: green">comp-b</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
name: 'CompB'
})
</script>
index.ts
import { App } from 'vue'
import CompB from './src/comp-b.vue'
// 为组件添加注册方法
CompB.install = (app: App): void => {
app.component(CompB.name, CompB)
}
export default CompB
3、组件入口
在packages/index.ts文件中编写代码,作为整个组件库的导出统一导出目录
import { App } from 'vue'
import CompA from './comp-a'
import CompB from './comp-b'
const components = [CompA, CompB]
// 注册所有的组件
const install = function (app: App): void {
components.forEach((component) => {
app.component(component.name, component)
})
}
// 导出注册方法
export default {
install
}
// 导出 单个组件
export { CompA, CompB }
三、组件的使用
1、全局使用
1.1、在examples/main.ts中导入组件,通过app.use注册所有组件
import { createApp } from 'vue'
import App from './App.vue'
import Components from '../packages'
const examples = createApp(App)
examples.use(Components)
examples.mount('#app')
export default examples
1.2、在页面中使用:
<template>
<div id="#app">
<comp-a />
<comp-b />
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
name: 'App'
})
</script>
1.3、效果:
2、在局部组件中引用
2.1、删除main.ts中对全局的引用
2.2、在页面中导入组件并且注册
<template>
<div id="#app">
<comp-a />
<comp-b />
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { CompA, CompB } from '../packages'
export default defineComponent({
name: 'App',
components: { CompA, CompB }
})
</script>
2.3、效果:
四、组件库打包
1、vue-cli打包
vue-cli工具提供了将vue打包为lib库的命令详细信息:cli.vuejs.org/zh/guide/bu…
在package.json的script字段下增加一条命令:
{
"scripts": {
"build:lib": "vue-cli-service build --target lib ./packages/index.ts"
}
}
通过命令行执行
yarn build:lib
或
npm run build:lib
即可打包为库文件
打包之后会生成cjs、umd格式的库,demo.html文件描述了该如何在html界面中使用这个库。
2、rollup打包
vue-cli打包之后仅仅生成了cjs和umd格式的库,对于一个组件库而言,可能还需要使用esm格式的库,如果在typescript项目中使用,或许还需要.d.ts类型声明文件。vue-cli打包并没有为我们提供这些支持,所以需要使用到rollup,使得我们的库能够得到更好的支持
2.1、安装rollup依赖
- rollup 打包工具
- rollup-plugin-terser 代码压缩工具
- plugin-node-resolve 第三方工具模块定位插件
- rollup-plugin-typescript 处理typescript文件
- rollup-plugin-vue vue处理插件
- rollup-plugin-css-only 处理样式(本文中未用到)
npm install -D rollup rollup-plugin-terser @rollup/plugin-node-resolve rollup-plugin-typescript2 rollup-plugin-vue rollup-plugin-css-only
或
yarn add -D rollup rollup-plugin-terser @rollup/plugin-node-resolve rollup-plugin-typescript2 rollup-plugin-vue rollup-plugin-css-only
2.2、ESM-bundle
- 在项目跟目录下创建build文件夹,用于存放打包需要的脚本文件
- 在build文件夹下创建rollup.config.bundle.js,使用rollup打包出具有所有组件的esm模块,以及各个组件的类型声明文件
rollup.config.bundle.js配置文件:
/* eslint-disable */
import path from 'path'
import pkg from '../package.json'
import { terser } from 'rollup-plugin-terser'
import { nodeResolve } from '@rollup/plugin-node-resolve'
import vue from 'rollup-plugin-vue'
import typescript from 'rollup-plugin-typescript2'
const deps = Object.keys(pkg.dependencies || {})
export default [
{
input: path.resolve(__dirname, '../packages/index.ts'), //入口
output: {
format: 'es',
file: 'lib/index.esm.js'
},
plugins: [
terser(),
nodeResolve(),
vue({
target: 'browser', // 服务端渲染使用 'node'
css: false,
exposeFilename: false
}),
typescript({
tsconfigOverride: {
compilerOptions: {
declaration: true
},
include: ['packages/**/*', 'typings/vue-shim.d.ts'],
exclude: ['node_modules']
},
abortOnError: false
})
], // 插件
external(id) {
return /^vue/.test(id) || deps.some((k) => new RegExp('^' + k).test(id))
}
}
]
- 在package.json文件中添加脚本,用于打包项目
{
"scripts": {
"build:esm-bundle": "rollup --config ./build/rollup.config.bundle.js"
}
}
2.3、UMD
- UMD格式脚本与esm格式基本相同,只不过需要指定output.name属性
/* eslint-disable */
import path from 'path'
import pkg from '../package.json'
import { terser } from 'rollup-plugin-terser'
import { nodeResolve } from '@rollup/plugin-node-resolve'
import vue from 'rollup-plugin-vue'
import typescript from 'rollup-plugin-typescript2'
const deps = Object.keys(pkg.dependencies || {})
export default [
{
input: path.resolve(__dirname, '../packages/index.ts'), //入口
output: {
format: 'umd', // umd格式
file: 'lib/index.umd.js', // 输出文件
name: pkg.name // 指定name
},
plugins: [
terser(),
nodeResolve(),
vue({
target: 'browser', // 服务端渲染使用 'node'
css: false,
exposeFilename: false
}),
typescript({
tsconfigOverride: {
compilerOptions: {
declaration: true
},
include: ['packages/**/*', 'typings/vue-shim.d.ts'],
exclude: ['node_modules']
},
abortOnError: false
})
], // 插件
external(id) {
return /^vue/.test(id) || deps.some((k) => new RegExp('^' + k).test(id))
}
}
]
五、发布
1、npm账号
1.1、注册账号,注册地址: www.npmjs.com/signup (已有账号)请忽略这一步
1.2、登录,通过命令行执行登录
npm login
登录成功检查:
npm whoami
2、修改package.json
2.1、设置private字段为false, 为true时 npm拒绝发布
{
"private": false
}
2.2、设置入口以及类型声明
{
"main": "lib/index.umd.js",
"module": "lib/index.esm.js",
"typings": "lib/index.d.ts"
}
3、发布
3.1、设置版本号
修改package.json中的version字段,保证该字段与已经发布的字段不重复
3.2、发布
执行命令:(发布前确保当前分支已经时一个干净的分支,即不含有未提交的文件)
npm publish
总结
至此,从0到1搭建一个组件库的基本框架便已经完成,其中还有诸多细节需要处理,如:
- css、scss等样式文件的处理
- 单个组件的分离
- ...
这一片文章谨献给想要维护一个自己的组件库,但是无从下手的初学者,同时更多深层次的内容仍需要继续探索。处于工作中的各位,将来势必会走到维护公司内部的业务组件库的地步,看过这篇文章,不至于真正需要用到的时候手足无措。更多细节敬请批评指正。
最后附上整个过程中所涉及到的代码:
GitHub: gitee.com/AloneH/vue-…
Gitee: gitee.com/AloneH/vue-…
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!