新建一个项目
可以使用webpack自己搭建,也可以使用脚手架搭建一个项目
这里为了快速给大家演示,我直接用vuecli4搭建一个项目
// 已经全局安装了vuecli4脚手架
vue create common_business
自定义选择想要的插件后,我们的项目就完成了
我们进入到项目中,把不要的文件都删除掉,最后的文件分布如下图:
- build:项目的配置文件
- examples:事例代码,可以在开发完成后进行测试,不会被打包
- lib:打包后的文件,使用这个组件实际就是引用了这个文件内容
- packages:封装组件的源代码,里面一个组件就是一个文件夹
- public:index.html文件,方便本地调试的
- static:一些需要的静态文件,一般情况下,是不需要这个文件夹的
- 其他:配置文件
封装组件
我们这次就封装一个alert
弹窗,该弹窗是基于element-ui的el-dialog
封装的,如图src文件夹下的Main.vue文件就是该组件的源码,源码部分我就不主要阐述了
跟src文件夹同级有一个index.js,这个文件主要是负责导出对应的组件的,如果你的组件库想要设置按需引入,那就需要在每一个组件里面导出自身
如下代码,其实就是在进行组件的注册
import AlertDialog from './src/Main.vue';
AlertDialog.install = function(Vue) {
Vue.component(AlertDialog.name, AlertDialog);
};
export default AlertDialog;
packages文件夹下还有一个index.js,这个js主要就是到处packages文件夹下的所有组件的:
我们把组件都放入数组中,实际上是可以方便我们做一个循环,而不必一个一个写死
import AlertDialog from './alert-dialog';
// 存储组件列表
const components = [
AlertDialog
]
// 定义 install 方法,接收 Vue 作为参数。如果使用 use 注册插件,则所有的组件都将被注册
const install = function (Vue) {
// 判断是否安装
if (install.installed) return
// 遍历注册全局组件
components.map(component => Vue.component(component.name, component))
}
// 判断是否是直接引入文件
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue)
}
export {
install,
AlertDialog
}
// 导出的对象必须具有 install,才能被 Vue.use() 方法安装
export default {
install,
AlertDialog
}
使用vue的同学应该都知道,在vue中如果我们想要注册一个组件,我们可以使用Vue.use(xxx)
,那具体是为什么呢?
查看vue源码你就会发现,我们在使用Vue.use(xxx)
的时候,实际是将Vue传递给xxx组件,并且调用xxx组件里面的install方法,这就是为什么我们的组件里面为什么必须要加一个install方法了
我看可以看看install方法帮我们做了什么?
其实就是在进行组件的注册
const install = function (Vue) {
// 判断是否安装
if (install.installed) return
// 遍历注册全局组件
components.map(component => Vue.component(component.name, component))
}
同时使用export default
和export
,是为了做既可以通过一个对象进行导出,又可以进行解构
好了,组件的封装就讲到这儿了
项目配置
如果我们想要讲组件打包成script标签可以引入的方式,我们需要设置libraryTarget
,这个target设置我下次会出文章详细讲述,这里就不赘述了,其实就是需要我们设置成umd
模式
新建vue.config.js
const devConfig = require('./build/config.dev')
const buildConfig = require('./build/config.build')
module.exports = process.env.NODE_ENV === 'development' ? devConfig : buildConfig
这里我是区分了两个环境的,为了更清晰,所以我直接区分成两个js
注意:如果你不需要进行本地调试,那你可以不需要配置dev环境,直接打包即可
我们先看看dev环境下的配置:
const pub = require('./config.common')
const path = require('path')
module.exports = {
pages: {
index: {
// page 的入口
entry: 'example/main.js',
// 模板来源
template: 'public/index.html',
// 在 dist/index.html 的输出
filename: 'index.html',
// 当使用 title 选项时,
title: '组件'
},
},
configureWebpack: {
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'@': resolve('examples')
}
},
},
chainWebpack: config => {
config.module
.rule('js')
.include.add(/packages/).end()
.include.add(/examples/).end()
.use('babel')
.loader('babel-loader')
.tap(options => {
// 修改它的选项...
return options
})
}
}
function resolve(dir) {
return path.join(__dirname, dir)
}
由于组件库的话,一般都会是比较独立的,不会引入太多依赖,引入太多依赖的组件,我们也不建议专门进行npm包的封装
所以我们这是配置了babel
以及入口文件entry
,上面已经写得很清楚了
下面我们来重点看看生产环境的打包配置:
module.exports = {
outputDir: resolve('lib'),
productionSourceMap: false,
publicPath: './',
configureWebpack: {
entry: {
'/': resolve('packages/index.js')
},
output: {
filename: '[name]/index.js',
libraryTarget: 'umd',
libraryExport: 'default',
library: 'CommonComponents'
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'@': resolve('examples')
}
},
},
css: {
sourceMap: true,
extract: {
filename: '[name]/style.css'
}
},
chainWebpack: config => {
config.module
.rule('js')
.include.add(/packages/).end()
.use('babel')
.loader('babel-loader')
.tap(options => {
// 修改它的选项...
return options
})
config.optimization.delete('splitChunks')
config.plugins.delete('copy')
config.plugins.delete('html')
config.plugins.delete('preload')
config.plugins.delete('prefetch')
config.plugins.delete('hmr')
config.entryPoints.delete('app')
}
}
function resolve(dir) {
// 路径可能与你的项目不同
return path.join(__dirname, dir)
}
首先需要配置ouput的文件夹,表示打包后的文件我们要放到lib文件夹下
outputDir: resolve('lib'),
然后收最重要的配置:
- filename:表示打包后文件的名字,我们把name写活,如果有多个组件,我们就好有多个文件夹
- libraryTarget:表示打包的模式,常见的是
_umd_
、_commonJs_
、_amd_
等 - libraryExport:将入口的默认到处分配给libraryTarget
- library:导出的库的名字,你的组件库暴露出去的名字
最后你执行npm run build,会出现一个lib文件夹,里面就会是你打包后的文件了output: {
filename: '[name]/index.js',
libraryTarget: 'umd',
libraryExport: 'default',
library: 'CommonComponents'
},
使用
先将你的项目发布到npm上
注意:npm publish
每次发布之前都需要更新一下版本号
npm上如何已经有你发布的包了,那你就可以去cdn上面找到你的包npm version patch
npm version minor // 1.1.0 表示新增一些小功能
npm version mmajor // 2.0.0 表示大的版本或大升级
npm version preminor // 1.1.0-0 后面多了个0,表示预发布
地址:https://www.jsdelivr.com/
去搜索一下你刚刚发布的包,如下图:
如果搜到了,你可以找到cdn地址,引入到你的项目中
打开想要使用组件的项目的index.html
,引入上面截图的地址:
在项目的入口文件进行注册:// index.html
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<script src="https://cdn.jsdelivr.net/npm/common_business@0.1.12/lib/index.min.js"></script>
</body>
在vue文件中使用:// main.js
const AlertDialog = CommonComponents.AlertDialog;
Vue.use(AlertDialog);
注意<template>
<div>
<el-button type="primary"
@click="alertVisible = true">打开通过script标签引入的alert弹窗组件</el-button>
<alert-dialog title="提示"
:visible.sync="alertVisible"
width="600px">
<div class="file-name-box">我在主应用使用</div>
</alert-dialog>
<router-view class="main-center"
ref="mainView" />
</div>
</template>
如果更新了版本,cdn上面搜索不到新版本内容,可能是cdn有缓存,你可以直接在浏览器直接通过修改版本号打开你需要引入的js,如果能打开,如果是发布成功的,你可以放心在项目里面使用
如下图:我发布了0.1.12,但是cdn上面没有这个版本,我就直接把0.1.11修改成0.1.12,如果浏览器返回正常,那就可以直接使用了