新建一个项目
可以使用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 patchnpm 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.jsconst 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,如果浏览器返回正常,那就可以直接使用了
