blog
blog copied to clipboard
从零开始搭建Vue组件库 (keywords: 组件库、 vue、 web component。)
tips: 阅读时间约为10分钟 keywords: 组件库、 vue、 web component。
为什么要做 ?
- 公司的业务迭代逐渐平稳,样式多变性逐渐消失,UI模块化已经形成规范。
- 开发人员不知道已经存在哪些组件,容易出现重复造轮子的情况。
- 易于管理和维护
- 独立部署之后UI也可以看到组件库写了哪些组件,方便设计的工作。
应该具备哪些功能
1. 可视化
一个组件库一定要有一个可以预览组件的地方
2. 文档
每个组件都要有一个说明文档
step 1 生成一个基础框架
构建vue组件库,直接可以拿来vue-cli初始化一个项目来做架子,一来方便,二来你可以直接测试你写的组件在项目中能不能run的起来。
执行 vue init webpack projectname
初始化一个项目
step 2 整理文件结构
我们只需要component 用来存放组件 和 pages 可以用来展示组件,其他我们可以先不管,或自行处理
有了写组件的地方,我们就可以开始编写组件了。
step 3 写一个组件
src/component/button/button.vue
src/component/button/button.scss
<style lang="scss" scoped>
@import './button.scss';
</style>
<template>
<button class="button">{{title}}</button>
</template>
<script>
export default {
name: 'Button',
data: () => ({
title: '这是一个button',
}),
}
</script>
.button {
width: 180px;
height: 60px;
font-size: 16px;
line-height: 60px;
text-align: center;
color: #fff;
cursor: pointer;
background-color: red;
}
组件写完了这时候要考虑的就是怎么让组件可以像element-ui一样 可以引入使用
step 4 打包组件 实现 import 方式使用
- 组件写好了,要注册才可以使用。 这个不多说 vue文档 vue组件注册
- 开发插件也需要有对应的方法 vue开发插件 Vue.js 的插件应该有一个公开方法 install。这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象:
- 拿上面的组件举例说明 前面提到1,2两点怎么使用:
src/component/button/index.js
import Button from './index.vue'
Button.install = Vue => Vue.component(Button.name, Button)
export default Button
step 5 ok 组件也有了 注册也搞定了 下面就是打包了 现在前端使用的打包工具无疑是webpack了 鉴于vue-cli初始化的项目用的webpack是3版本的,我们就要这个版本的写法来写 webpack
需要考虑的问题
- 入口?
- 出口?
- 编译那些类型文件?
- 压缩混淆?
- style独立?
这里我就不多说了,网上文章很多。自己看文档也不难, 这是我的写法。不懂的直接搜相关的字段就可以得到相应的文章
let path = require('path')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
module.exports = {
context: path.resolve(__dirname, './src/components/'),
entry: './index.js',
output: {
path: path.resolve(__dirname, './packages/lib'),
filename: 'index.js',
library: 'name', // 指定的就是你使用require时的模块名
libraryTarget: 'umd', // libraryTarget会生成不同umd的代码,可以只是commonjs标准的,也可以是指amd标准的,也可以只是通过script标签引入的
umdNamedDefine: true, // 会对 UMD 的构建过程中的 AMD 模块进行命名。否则就使用匿名的 define
},
module: {
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader',
],
},
{
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader',
],
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
css: ExtractTextPlugin.extract({
use: ['css-loader', 'sass-loader'],
fallback: 'vue-style-loader',
}),
},
extractCSS: true,
},
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]',
},
},
],
},
resolve: {
alias: {
'~': path.resolve(__dirname, '../components'),
},
extensions: ['*', '.js', '.vue', '.json'],
},
performance: {
hints: false,
},
devtool: '#source-map',
plugins: [
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false,
},
},
sourceMap: true,
parallel: true,
}),
new OptimizeCSSPlugin({
cssProcessorOptions: {
safe: true,
map: { inline: false },
discardComments: {
removeAll: true,
},
},
}),
new ExtractTextPlugin('style.css'),
],
}
这时候当你运行打包命令 webpack --config (这里跟你的webpack.config.js路径)
就会生成对应的文件了
step 6 生成了包之后就是发布npm
包,发包过程直接google就可以了。
图中的 index.js
文件就是作为npm
包的入口文件
{
"name": "component",
"version": "1.0.0",
"description": "vue component",
"main": "./lib/index.js",
"directories": {
"lib": "lib"
},
"repository": {
"type": "git",
"url": "githuburl"
},
"keywords": [
"组件",
],
"author": "you name",
"license": "ISC"
}
step 7 在项目中使用跟element-ui 使用完全一致 将element-ui 替换成你的包名就可以了
import Vue from 'vue'
import Element from 'element-ui'
Vue.use(Element)
// or
import {
Select,
Button
// ...
} from 'element-ui'
Vue.component(Select.name, Select)
Vue.component(Button.name, Button)
至此 一个组件库开发就完结了。当然过程并没有这么顺利,还是遇到了一些问题。但是都不至于非常棘手,如果你在过程中遇到问题可以在这里提问,有时间我会解答。
问题 1 nuxt 中使用 ssr 服务端渲染组件的时候发现报错 window or document is not defined
这个问题排查了很久,思路陷入了怎么写一个服务端渲染的组件。 最后发现是因为打包的过程中,没有抽离css文件,导致js会使用docment动态添加样式 所以打包出来的index.js 有 window 和 document 字段,抽离css样式 就会fix
问题 2 既然维护的是一个库, 就要有一个规范,包括代码规范,提交规范。
-
代码规范 代码规范 我们直接依赖
eslint
使用eslint-config-standard
相关规则 -
提交规范 一个代码的提交日志,是快速定位问题解决问题的关键字,所以提交规范很重要 框架中使用了
husky
强制在提交之前进行commit message 检查 不符合规范直接fail 并给予提示
问题 3 CHANGELOG 版本日志是有必要的,好的版本日志依赖于好的提交 所以我们前面强制了提交规范 为版本日志打下了良好的基础
conventional-changelog-cli
版本日志插件
一行命令根据提交记录生成日志
问题 4 组件预览怎么做?
组件预览可以自己写一个页面来做,但是重复工作太多,还要自己定义目录结构有些麻烦就找一个了框架来帮我们干活 storybook 使用起来比较简单 而且支持搜索和自动生成目录结构
should support import on demand which is like
import {Button} from 'your-lib'
should support import on demand which is like
import {Button} from 'your-lib'
It's a good idea. It's very simple, you can do it yourself。