基于vue的ui组件库开发—— 04

104 阅读3分钟

前言

上一篇文章中通过全局引入的方式,展示了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)