3

Vue组件库开发总结

由于工作需要,最近在学习怎么开发一个Vue组件库。主要需要实现以下点:
1.组件使用npm包引入
2.实现按需引入及按需打包
项目中许多实现是参考的element-ui,特别是webpack打包部分

组织项目

项目生成

项目生成是直接用的vue-cli,在根目录下增加了一个index.js,用于组件打包的入口文件,两个webpack打包文件,以及一个组件的json文件,用于之后的按需引入的打包。组件放置在src/cmps中,目录结构如下图:
project-dir

组件结构

由于我的组件把样式都写在了vue里面,所以没有单独的样式文件,就是一个Vue文件和一个js入口文件
图片描述

组件编写

单个组件编写

vue组件的编写需要按照官方的vue插件开发规范来。为了实现后续的按需打包,在每一组件的入口文件中,都需要定义install方法,并随组件一同暴露出来

import Button from './index.vue'
Button.intall = function (vue) {
  vue.component(Button.name, Button)
}
export default Button

所有组件输出编写

所有组件的输出就是将所有组件暴露出去,并加上一个对所有组件的install方法。其中if(window && window.Vue) install(window.Vue)是用来实现script标签引入的方式的。

import Input from 'src/cmps/input/index.js'
import Toast from 'src/cmps/toast/index.js'
import Button from 'src/cmps/button/index.js'

const cmps = [
  Input,
  Toast,
  Button
]

const install = vue => {
  cmps.map(cmp => {
    vue.component(cmp.name, cmp)
  })
}
if(window && window.Vue) install(window.Vue)

export default {
  install,
  Input,
  Toast,
  Button
}

组件打包

全量加载的打包

全量加载的打包首先是把vue-cli生成的webpack文件改一下打包的出入口文件和路径就行了。为了方便之后的按需加载的打包,出口文件我的路径放在了lib目录下。
为了实现npm包、script标签等引入形式,libraryTarget选择了umd模式。library是npm包引入时的名称。entry的写法是我为了用dev在本地测试组件是否可用而写的。externals是为了去除在组件库和实际项目中会重复的库,比如vue

entry: ENV == 'dev'? path.resolve(__dirname, './src/main.js'): path.resolve(__dirname, './index.js'),
output: {
  path: path.resolve(__dirname, './lib'),
  publicPath: '/dist/',
  filename: 'input-ui.js',
  library: 'input-ui',
  libraryExport: 'default',
  libraryTarget: 'umd'
},
externals: {
  vue: 'vue'
}

package.json中需要加入对主入口的说明

"main": "lib/input-ui.js"

按需加载的打包

按需加载的打包主要是参考了element-ui的代码。需要对每个组件单独打包,以及对所有组件全量打包。其实我没有明白这里的全量打包和上面说的量加载的全量打包有什么区别。好像是libraryTarget不一样,element-ui中,全量打包的主入口文件的libraryTarget是commonjs2,而按需打包中的主入口文件的libraryTarget是umd。我这里的libraryTarget是随便写的,因为我其实并不需要用到采用script标签的引入方式。
按需加载的打包是将所有组件单独打包,和全量打包的差别也只是出入口的差别。

const entry = require('./comps.json')
module.exports = {
  entry ,
  output: {
    path: path.resolve(__dirname, './lib'),
    publicPath: '/dist/',
    filename: '[name].js',
    chunkFilename: '[id].js',
    libraryTarget: 'commonjs2'
  },

comps.json

{
  "input": "./src/cmps/input",
  "toast": "./src/cmps/toast",
  "button": "./src/cmps/button"
}

按需打包的使用

要使用按需打包,不仅组件库的打包需要做处理,项目中也需要做处理。通过上面的方式打包的组件库,在项目中可以使用babel-plugin-component来实现按需打包。
在.babelrc中加入这个组件。libraryName是需要按需打包的库名。由于我的简陋的组件中,没有引用单独的样式,所以style设成了false,不然在引用组件时,还需要获取一个样式文件。之前提到为了方便按需打包,所以打包后的目录是lib,这是由于babel-plugin-component默认的库的目录就是lib,如果需要修改目录只需要加入"libDir": "lib"具体的babel-plugin-component的使用可以官方的readme。

"plugins": [["component", {
  "libraryName": "input-ui",
  "style": false
}]]

然后就可以在项目中使用按需引入的方式来使用组件了

import {Input, Button} from 'input-ui'
Vue.component(Input.name, Input)
Vue.component(Button.name, Button)

npm包本地测试

在发布npm包之前,我们需要先在本地测试这个包是否到达我们预想的效果。这时,我们可以使用npm link把我们需要测试的包link到npm本地的全局。再在本地测试项目中通过npm link 本地测试的包名把我们要测试的本地包引入测试项目中,便可以对我们只做的组件库npm包进行本地测试了。

npm包发布

首先需要在npm官网注册账号。npmjs.com
然后添加用户npm adduser填入账号密码及邮箱。
通过npm publish发布包就行了。如果遇到报错说没有权限发布该包,基本上是因为这个包名已被使用。换个其他的名字就行了。而且每次发布包都需要修改版本号,不同发布两个相同的版本号。

最后

这是本人第一次写文章,而且本人水平有限,对webpack的打包,其实并不是很了解,所以写的有些乱,甚至可能有些错误,请大家及时指出,感谢。gitHub


mooooore
9 声望1 粉丝