前言
前两章我们从搭建基础的组件库开发架构,然后实现了几个基本的组件库的开发,并且在demo中得到了验证。接下来要面临的一个核心问题就是:如何将本地开发好的组件库打包发布到npm中,并且正确的在项目工程中使用呢?
1. 构建组件库并且完整引入的方法
在没有头绪的情况下,往往我们会想着参考一下已有的成熟的组件库,例如优秀的 element-ui
源码中是如何处理的?话不多说,我们直接看源码。
element-ui
中有两个很核心的文件目录:lib
和 packages
。
lib
文件夹包含编译后的组件库的入口文件,通常是 UMD 格式,可以在全局环境中通过<script>
标签直接引用。用于发布到 npm之后,也可以通过 npm 安装后直接使用;packages
文件夹包含了每个组件作为一个单独模块的入口文件,通常是 CommonJS 格式,每个组件都有自己的文件夹,包含了组件的.vue
文件、样式文件和测试文件。用于支持 Tree Shaking,即在构建项目时只包含使用到的组件,以减少最终打包文件的大小。
本章节我们主要要实现我们自己的组件库的完整引入,即 将components目录下的所有ui组件打包,使我们的demo项目工程可以正常引入并且ui效果正常
。其实 vue-cli
官方提供了一个官方方法,支持将项目作为一个库的方式来进行打包。如下命令可以将一个单独的入口构建为一个库,这个入口可以是一个 .js
或者一个 .vue
文件。
vue-cli-service build --target lib --name [输出文件名称] [入口文件]
通过上述命令执行后,构建的一个库会输出例如如下的内容:
dist/myLib.common.js
一个给打包器用的 CommonJS 包;dist/myLib.umd.js
一个直接给浏览器或 AMD loader 使用的 UMD 包;dist/myLib.umd.min.js
压缩后的 UMD 构建版本;dist/myLib.css
提取出来的 CSS 文件 (可以通过在vue.config.js
中设置css: { extract: false }
强制内联, 这样css文件就不会生成)
File Size Gzipped
dist/myLib.umd.min.js 13.28 kb 8.42 kb
dist/myLib.umd.js 20.95 kb 10.22 kb
dist/myLib.common.js 20.57 kb 10.09 kb
dist/myLib.css 0.33 kb 0.23 kb
2. 组件库打包构建实践
按照上面的方法,我们开始实践。首先我们知道前两章内容中,demo项目的构建配置依赖 vue.config.js
,但是我们希望可以通过package.json
不同脚本命令,来实现不同类型的构建目标,因此需要将vue.config.js
改造一下,希望通过接受不同的全局变量 MODE_TYPE
值,来实现不同的打包构建效果。
// vue.config.js
const MODE_TYPE = process.env.MODE_TYPE; // 获取package.json 的 MODE_TYPE 类型
if(MODE_TYPE === 'demo') {
module.exports = require('./config/demo');
}
if(MODE_TYPE === 'lib') {
module.exports = require('./config/lib');
}
在根目录中新增一个config
目录,在该目录下新增两个文件demo.js
和 lib.js
。其中 demo.js
是之前vue.config.js
中构建demo项目的代码;lib.js
是我们本篇文章中用来构建组件库的配置代码。这两个文件统一在 config
目录下管理,vue.config.js
改写成上述代码,通过获取 process.env.MODE_TYPE
来分别执行不同的构建脚本。对应的 package.json
和 lib.js
的配置如下:
...
"scripts": {
"serve": "MODE_TYPE=demo vue-cli-service serve",
"build": "MODE_TYPE=demo vue-cli-service build",
"build:lib": "MODE_TYPE=lib vue-cli-service build --target lib --name index components/index.js",
},
...
// lib.js
const { defineConfig } = require("@vue/cli-service");
module.exports = defineConfig({
outputDir: "lib",
css: {
extract: false, // extract 为 false 表示内联了css样式,在全局导入中适用
sourceMap: true
},
chainWebpack: config => {
// 配置库导出模式
config.output.libraryTarget('umd');
}
});
上述配置完成之后,执行命令:npm run build:lib
,就会在根目录下生成 lib
文件目录,里面包含打包构建好的所有ui组件源码。
3. demo 项目中验证
在主入口 main.js
中引用,效果正常。
import Vue from 'vue'
import App from './App.vue'
import AskbobUi from '../lib/index.common'
import '@/index.less'
Vue.use(AskbobUi)
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')