之前写了一篇文章:NPM 包发包流程,大致介绍了如何通过 npm 发布一个自己的包;这一篇介绍一下如何发布一个自己的 vue 组件库到 npm 上;
一、背景
为什么要在 npm 上发布自己的 vue 组件库呢? 我们都知道在项目开发过程中,经常会遇到相似功能或者可以复用的模块;如果是在同一个项目中我们可以封装一个公用的组件来进行复用; 如果公司里面多个项目都有可以复用的模块呢?最简单的当然是直接复制一份到不同的项目中,但是这样在后期维护过程中,一个地方有变动你就需要在不同的项目中多次进行修改,这样就不怎么友好了;我们只要将组件上传到 npm 包管理工具上,在不同的项目中进行引入调用,如果有变动只需要更新 npm 上面的组件包就可以了;
二、准备工作
文本主要是基于 vue-cli3 构建的项目来封装组件;当然还有其他的方法,可以根据自己的喜好和能力选择;文章的后面还会简单介绍一下 vue init webpack-simple 构建的项目如何发包; 1、创建项目
vue create name
脚手架创建项目,这样很多配置虽然用不到,但是很方便; 2、新建文件夹: 如上图,新建 components 文件夹用来存放组件,组件文件夹内部新建 index.js 文件用来导出当前组件,在 src 同级新建 index.js 用来统一导出组件;
三、组件准备
本文以 calendar 组件为例,对比上面的目录: 1、src/components/calendar/index.vue
<template>
<div>
<div style="border-bottom: 1px solid #ccc; padding-bottom: 10px;">
<el-select @change="skip('year')" v-model="Nyear" filterable placeholder="请选择">
<el-option
v-for="item in year"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<el-select @change="skip('month')" v-model="Nmonth" filterable placeholder="请选择">
<el-option
v-for="item in month"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
<el-calendar v-model="value" ref="monChild">
<template slot="dateCell" slot-scope="{date,data}">
<div class="date-content">
<!--周末不显示签到信息,并且置灰-->
<p v-if="isWeekend(date)" style="display: flex; flex-direction: column; align-items: center;">
<span style="color: #C0C4CC;" disabled>{{getDay(date)}}</span>
</p>
<p v-else style="display: flex; flex-direction: column; align-items: center;">
<span>{{ getDay(date) }}</span>
<template v-if="needData(date,data)">
<span v-if="arrInfo.indexOf(data.day) > -1" style="line-height: 30px; color: #ccc; display: flex; flex-direction: column; align-items: center;">
已签
</span>
<span v-else style="color: red; line-height: 30px; ">未签</span>
</template>
</p>
</div>
</template>
</el-calendar>
</div>
</template>
<script>
export default {
name:"calendar",
data(){
return{
value:new Date(),
arrInfo:['2022-02-01','2022-02-03'],
Nyear:`${new Date().getFullYear()}`,
Nmonth:`${new Date().getMonth() + 1}`,
year:[{value:'2021',label:'2021年'},{value:'2022',label:'2022年'}],
month:[
{value:'1',label:'1月'},
{value:'2',label:'2月'},
{value:'3',label:'3月'},
{value:'4',label:'4月'},
{value:'5',label:'5月'},
{value:'6',label:'6月'},
{value:'7',label:'7月'},
{value:'8',label:'8月'},
{value:'9',label:'9月'},
{value:'10',label:'10月'},
{value:'11',label:'11月'},
{value:'12',label:'12月'}
]
}
},
mounted(){
this.$el.querySelector("div.el-calendar__header").remove();
},
methods:{
needData(date,data){
let curData = `${date.getFullYear()}-${date.getMonth()}`
let newData = `${new Date().getFullYear()}-${new Date().getMonth()}`
if(data.type == 'current-month'){
let curDay = date.getDate();
let newDay = new Date().getDate();
if((curData == newData) && (curDay <= newDay)){
return true
}else if(curData != newData){
return true
}
}else {
return false
}
},
isWeekend(date){
if(date.getDay() == 0 || date.getDay() == 6){
return true;
}else {
return false
}
},
skip(type){
if(type == 'year'){
this.Nmonth = '1';
}
let value = new Date(`${this.Nyear}-${this.Nmonth}`);
this.value = new Date(value)
},
getDay(date) {
return date.getDate()
}
}
}
</script>
<style>
.el-calendar-table:not(.is-range) td.next, .el-calendar-table:not(.is-range) td.prev {pointer-events: none;}
</style>
2、src/components/calendar/index.js,暴露单个组件,提供按需加载功能;
import calendar from './index.vue'
calendar.install = function(Vue){
Vue.component(calendar.name, calendar)
}
export default calendar
3、src/index.js,将组件导入,提供统一安装的 install 方法,并导出;
import calendar from './src/components/calendar'
let components = [calendar]
let install = function(Vue){
if(install.installed) return
components.map(item => {
Vue.component(item.name, item)
})
}
if(typeof window !== 'undefined' && window.Vue){
install(window.Vue)
}
export default {
install,
calendar
}
4、本地调试 在 main.js 文件内部引入
import xxsui from '../index.js'
Vue.use(xxsui)
然后就可以在整个项目里使用所以的组件了,测试通过之后我们的组件就准备好了;
四、发包
1、src/package.json
"name": "xxsui",
"version": "1.0.0",
"author": "xinsen.xiong <2575326615@qq.com>",
"license": "MIT",
"private": false,
"main": "./lib/xxsui.umd.min",
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lib": "vue-cli-service build --target lib --name xxsui --dest lib index.js"
},
将 private 设置为false,并添加 author、license、main、version、name、keywords 、description 等,同时需要修改打包后生产的文件,在 scripts 里面新增一个 lib 指令,目标 lib,指定打包后文件名 xxsui ,打包指向 index.js,最终生成文件在 lib 文件里: 我们要的是 xxsui.umd.min.js 这个文件,也是 main 指向的文件; 2、控制台执行命令打包项目
npm run lib
3、npm 发包
npm login
npm publish
4、发包成功之后可以在 npm 官网查看是否存在组件包,以及版本时间 这样发包就结束了;
五、使用
新建一个项目,然后在项目中安装引入刚才发的包 安装:
npm i xxsui -s
引入:
inport xxsui from 'xxsui'
Vue.use(xxsui)
然后在项目中直接使用 xxsui 组件库中的组件,到这里整个依赖于 vue-cli3 搭建的组件库发包就完成了;
注意:如果 xxsui 组件库使用了其他组件库例如 elementui,在项目中使用 xxsui 的时候也需要将 elementui 安装引入;
六、webpack-simple 构建项目发包
这种方式发包和上面的基本上差不多,只是在 package.json 配置有所不同,然后多一个 webpack.config.js 的配置; 1、 package.json 将 private 设置为false,并添加 author、license、main、version、name、keywords 、description 等;其中 main 指向的是 webpack.config.js 中 output 中的 filename;
"name": "xxsui",
"version": "1.0.0",
"author": "xinsen.xiong <2575326615@qq.com>",
"license": "MIT",
"private": false,
"main": "./dist/xxsui",
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
},
这里自动生成的 scripts 不需要修改; 2、 webpack.config.js
entry: './index.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'xxsui.js'
},
修改入口、出口,入口文件改为组件暴露的出口 index.js 文件;出口暴露出来的文件名修改为 js 文件;
最后
不管用什么方法创建的项目,最终都是要把文件打包成一个 js 文件;区别就是 vue-cli3 内部已经做了大量的处理,只需要修改 package.json 里面的打包配置就可以了,而 webpack-simple 需要自己配置打包文件的入口、出口;
如有错误或者遗漏,欢迎留言指正!!!
|