在日常工作中,会编写一些通用组件,但通用的组件常常需要在各个项目中使用,于是就有了打包发布自己的组件库的需求,这里参考了 ant-design-vue 的源码学着做了一个简单的示例。
ant-design-vue库的使用流程是这样的:在main.js中引入ant-design-vue包和样式文件,然后Vue.use就好了,在页面上就可以直接使用,所以这里也参考这样的使用方式来开发自己的组件库。
import Vue from "vue";
import App from "./App.vue";
// 引入 ant design
import Antd from "ant-design-vue";
// 引入 ant design 样式
import "ant-design-vue/dist/antd.less";
Vue.use(Antd);
new Vue({
render: (h) => h(App),
}).$mount("#app");
这里用的是vue2.x、webpack4.x、less来做的,相关的使用和配置可参考对应版本的文档
1,创建项目
创建一个vue项目,用于预览vue组件的效果
vue create moss-ui
由于我这里要用到less,所以还得安装一些less-loader
yarn add less-loader@6.2.0 -D
2,编写组件(在根目录下新建一个components目录)
大致代码如下:
components/button/Button.vue
<template>
<button class="xx-button">
<slot></slot>
</button>
</template>
<script>
export default {
name: "xx-button",
};
</script>
components/button/Button.less
@import "../style/global.less";
.xx-button {
color: #fff;
background-color: @primary-color;
padding: 10px;
border: none;
&:hover {
background-color: lighten(@primary-color, 10%);
}
}
components/style/global.less
@primary-color: #e55039;
components/style/index.less(引入所有组件的样式)
@import "../button/Button.less";
@import "../tag/Tag.less";
components/components.js(引入并导出所有的组件)
export { default as XxButton } from "./button/Button";
export { default as XxTag } from "./tag/Tag";
components/index.js(要打包的文件)
先引入所有的组件以及组件的样式文件,然后编写install函数(vue插件所需,可参考v2.cn.vuejs.org/v2/guide/pl…),在install函数中注册所有组件,最后导出install
import * as components from "./components";
import "./style/index.less";
const _components = Object.values(components);
function install(Vue) {
_components.forEach((component) => {
Vue.component(component.name, component);
});
}
export default {
install
};
到这里,组件就算是完成了,可以编写一个vue页面来预览下组件的效果。
main.js
import Vue from "vue";
import App from "./App.vue";
// 引入组件
import components from "../components";
// 引入组件样式
import "../components/style/index.less";
Vue.config.productionTip = false;
// 使用组件
Vue.use(components);
new Vue({
render: (h) => h(App),
}).$mount("#app");
App.vue
<template>
<div id="app">
<h1>moss-ui</h1>
<div>
<xx-button>button</xx-button>
</div>
<div>
<xx-tag>tag</xx-tag>
</div>
</div>
</template>
3,打包组件
1,修改package.json文件
- name 包名称
- version 包版本号
- private 为true的话上传不了到npm或nexus的
- files 是需要上传的文件或目录,如果不写会把所有的代码都上传(lib是打包后的代码目录)
- main 是指定使用的主程序文件(import MossUI from 'moss-ui' 的时候其实是会指向到这个文件来的)
vue-cli-service build --mode lib --target lib --name moss-ui --dest lib components/index.js这句命令会将components/index.js文件打包到lib目录(相关参数可参考:cli.vuejs.org/zh/guide/cl…)
{
"name": "moss-ui",
"version": "1.0.0",
"private": false,
"main": "lib/moss-ui.umd.min.js",
"files": [
"lib"
],
"scripts": {
"serve": "vue-cli-service serve --mode dev",
"build": "vue-cli-service build --mode production",
"lint": "vue-cli-service lint",
"lib": "vue-cli-service build --mode lib --target lib --name moss-ui --dest lib components/index.js"
}
.....
}
2,执行yarn lib会生成打包后的文件
3,将main.js修改下,然后再预览效果,组件如预期显示了说明打包没问题了
import Vue from "vue";
import App from "./App.vue";
// 引入组件
import components from "../lib/moss-ui.umd";
// 使用组件
Vue.use(components);
new Vue({
render: (h) => h(App),
}).$mount("#app");
上面的打包会把css也打包进去,如果我们需要独立提取出css文件来,那可以修改配置文件vue.config.js(没有则创建一个)
module.exports = {
......
css: {
extract: true, // 添加该配置会独立提取出css文件来
}
}
修改配置后重新打包,可以看到css文件被提取出来了
但这样的css是将less编译后的,如果想要在项目中覆盖组件的全局变量就不行了,按ant-design-vue的用法是可以引入less文件,例如这样:
import "ant-design-vue/dist/antd.less";
那这里就需要在打包的时候把所有的less文件也拷贝到lib目录下, 这样使用的时候就能直接引入了,这里就需要使用到CopyWebpackPlugin插件了,这个插件vue-cli内置了,所以直接使用就可以了(具体使用可参考:v4.webpack.js.org/plugins/cop…)
修改vue.config.js文件
- from是需要被拷贝的文件路径,比如将components目录下所有的less文件拷贝出来
- to是目的地文件路径,这里按源文件的路径、名称、后缀原样拷贝
- toType这里要填写template,否则to中的变量会被解析成字符串
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
......
css: {
extract: true,
},
chainWebpack: (config) => {
config.plugin("copyWebpackPlugin").use(
new CopyWebpackPlugin([
{
from: "components/**/*.less",
to: "[path][name].[ext]",
toType: "template",
},
])
);
},
};
再重新打包后,目录下的所有less文件被拷贝出来了
修改main.js,效果如预期一样
import Vue from "vue";
import App from "./App.vue";
import components from "../lib/moss-ui.umd";
import "../lib/components/style/index.less";
Vue.config.productionTip = false;
Vue.use(components);
new Vue({
render: (h) => h(App),
}).$mount("#app");
在项目中覆盖组件中的全局变量需要添加loaderOptions配置(参考:cli.vuejs.org/zh/config/#…)
module.exports = {
......
css: {
extract: true,
loaderOptions: {
less: {
lessOptions: {
modifyVars: {
"@primary-color": "#575fcf",
},
javascriptEnabled: true,
},
},
},
},
......
};
添加配置后再打包,效果如下:
发布组件
这样一个基本的组件就算开发完成了,那么就可以开始推送到npm或nexus上了,我这里以公司内网搭建的nexus为示例(npm注册地址:www.npmjs.com/signup)
1,注册账号
2,登录 npm login --registry=https://xxx.com/repository/npm-xxx,输入账号、密码、邮箱
3,推送 npm publish --registry=https://xxx.com/repository/npm-xxx
大功告成,这样就可以在项目里去安装使用了
1,安装包 npm install moss-ui --registry=https://xxx.com/repository/npm-group
2,引入包,启动项目预览,效果如预期的一样一样
import Vue from "vue";
import App from "./App.vue";
import components from "moss-ui";
import "moss-ui/lib/components/style/index.less";
Vue.config.productionTip = false;
Vue.use(components);
new Vue({
render: (h) => h(App),
}).$mount("#app");
最后奉上项目示例:github.com/leietal/mos…