前言
上一篇文章中通过全局引入的方式,展示了ui组件的效果,我们需要思考一个问题:当前前端在日益追求高性能的前提下,通过全局引入的方式直接引入组件库是否可行?例如我们可能只需要使用 button
按钮,如果组件库很大,岂不是会加重前段资源的负担,因此本章我们要实现组件局部引入。
1. 多入口打包配置
我们的目的是要将组件库打包后可以支持局部引入,那就需要通过多入口打包的形式,再生成打包文件,在 config
目录下新增一个 packages.js
文件,作为组件局部引入方案的打包配置,在 package.json
中新增局部打包的执行命令。
"scripts": {
...
"build:packages": "MODE_TYPE=packages vue-cli-service build",
...
},
在 vue.config.js
增加配置:
...
// 组件单独打包,可以局部引入
if(MODE_TYPE === 'packages') {
module.exports = require('./config/packages');
}
packages.js
的配置如下,可以看到下面配置的核心在于多入口配置,通过引入插件 glob
读取本地components
中的文件,便利该目录下的文件,通过 config.entry('xxx').add('../../xxx')
的方法新增入口,配置输出之后生成多个目录文件。这么做的目的就是要将不同的组件隔离,便于我们局部引入
。
const { defineConfig } = require("@vue/cli-service");
const path = require("path");
const glob = require('glob');
module.exports = defineConfig({
outputDir: "packages",
publicPath: './',
css: {
extract: false, // extract 为 false 表示内联了css样式,在全局导入中适用
sourceMap: true
},
productionSourceMap: false,
chainWebpack: config => {
// 配置多入口
const files = glob.sync('components/!(utils)/index.js'); // 处理除了util文件外的其他所有文件
files.forEach(file => {
const comReg = new RegExp(/components\/(.*)\/index.js/i);
const fReg = file.match(comReg);
config.entry(fReg[1]).add('./' + file);
});
// 输出配置
config.output
.filename('[name]/index.js')
.chunkFilename('[name].js')
.libraryTarget('umd')
.library();
// 默认入口有app,删掉
config.entryPoints.delete('app');
// 避免vue被打包
config.externals({
vue: {
commonjs: 'vue',
commonjs2: 'vue',
root: 'Vue',
},
});
config.plugins
.delete("copy") // 禁止把public的东西进行复制
.delete("html") // 禁止生成html文件
// 这个必须配置!!!不然默认会进行拆包,被打包后的组件被引入时就会报错
config.optimization.splitChunks({
cacheGroups: {},
});
}
});
完成以上的配置之后,我们执行一下脚本: npm run build:packages
,可以发现根目录下生成新的文件 packages
,日志如下:
Compiled successfully in 3387ms 5:00:27 PM
File Size Gzipped
packages/test/index.js 6.48 KiB 2.73 KiB
packages/nav-bar/index.js 2.94 KiB 1.20 KiB
packages/button/index.js 1.93 KiB 0.91 KiB
packages/icon/index.js 1.91 KiB 0.89 KiB
Images and other types of assets omitted.
Build at: 2024-10-10T09:00:27.559Z - Hash: 2be0f1245dce4837 - Time: 3387ms
好的,完成了以上的打包任务,我们还需要在 demo
项目中实践,毕竟实践是检验真理的唯一标准。在 main.js
中引入,如下图所示,我们需要什么组件就引入什么组件。引入之后启动 demo
项目,效果展示正常。
// 组件引入方式2: 手动按需引入
import '@/index.less'
import Button from '../packages/button'
import Icon from '../packages/icon'
import Navbar from '../packages/nav-bar'
import Test from '../packages/test'
Vue.component(Button.name, Button)
Vue.component(Icon.name, Icon)
Vue.component(Navbar.name, Navbar)
Vue.component(Test.name, Test)