使用 unplugin-vue-components 按需引入组件(内附实现原理)

简介: 使用 unplugin-vue-components 按需引入组件(内附实现原理)

我们开发 Vue 项目时,一般会使用组件库进行开发,组件库有两种加载方式:全局引入按需引入

全局引入组件库,使用起来就非常方便,但是坏处就是产物体积大,对性能要求较高的项目不友好。

按需引入,可以减少体积大小,但需要通过以下方式加载组件:


import Button from 'ant-design-vue/lib/button';
import 'ant-design-vue/lib/button/style';
// 或者 ant-design-vue/lib/button/style/css 加载 css 文件

引入组件还需要引入样式,非常麻烦,因此有了 babel-plugin-import 来进行按需加载,加入这个插件后,可以省去 style 的引入。


import { Button } from 'ant-design-vue';

但这种仍然需要手动引入组件,而且还必须使用 babel

而  unplugin-vue-components 可以不需要手动引入组件,能够让开发者就像全局组件那样进行开发,但实际上又是按需引入,且不限制打包工具,不需要使用 babel


使用效果


Antd Vuevite 为例:


import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers'
export default {
  plugins: [
    Components({
      resolvers: [
          AntDesignVueResolver()
      ],
    }),
  ],
};

这样就能自动引入 Antd Vue 的组件,不需要手动 import 组件以及组件样式,使用起来就像全局组件一样,但这是按需自动引入,可以减少产物大小。


<template>
  <a-button>按钮</a-button>
</template>

这样直接使用即可

解析器


unplugin-vue-components 为主流的 UI 组件库提供了内置的支持,通过使用对应 UI 组件库的解析器(resolvers),就能自动引入对应的组件库组件及样式

解析器可以是一个函数或者是对象

以对象为例:


{
    type: 'component',
    resolve: (name: string) => {
        const map = {
            'Abutton': 'Button'
        }
        const path = `ant-design-vue/es`
        const name = map[name]
        return {
          // Button
          name,   
          // ant-design-vue/es
          from: path, 
          // ant-design-vue/es/button/style/css
          sideEffects: `ant-design-vue/es/${name.toLowerCase()}/style/css`, 
        }
      }
    },
  }
}

resolve 是一个函数,当遇到 a-button 时,就会调用该函数,入参是 AButton

函数需要返回一个对象,例如:


{
  name: 'Button',   
  from: 'ant-design-vue/es',  
  sideEffects: 'ant-design-vue/es/button/style/css',  
}

这样 unplugin-vue-components  就会加入以下代码:


import { Button } from 'ant-design-vue/es'
import 'ant-design-vue/es/button/style/css'

ant-design-vue/es/button/style/css 中,引入了 Button 组件相关的样式:


import '../../style/default.css';
import './index.css';

一般情况按需引入组件,需要把组件的样式也引入进来,这就是 sideEffects 的作用。


实现原理


可能大家会想到,将 Vue 处理成以下内容即可:


<template>
  <a-button>按钮</a-button>
</template>
<script setup>
import { Button as AButton } from 'ant-design-vue/es'
import 'ant-design-vue/es/button/style/css'
</script>

看起来可行,但其实不行,因为你 script 有普通的写法和 setup 写法,如果要做,得兼容两种情况,比较复杂。

其实 unplugin-vue-components 的实现非常简单。我们直接来看看 Vue 编译后的代码

1686404724870.png

可以看到,全局组件编译后会用 resolveComponent 包裹,该函数在 Vue 官网有说明,就是按名称找到已注册的全局组件。

unplugin-vue-components 只需要正则匹配 _resolveComponent,拿到入参 a-button,然后根据将名称标准化为 AButton,然后交给解析器,解析器会返回如下对象:


{
  name: 'Button',   
  from: 'ant-design-vue/es',  
  sideEffects: 'ant-design-vue/es/button/style/css',  
}

然后修改 Vue 编译后的代码(unplugin-vue-components 会在 Vue 插件之后执行

1686404700366.png

引入以下代码:


import { Button as __unplugin_components_0 } from 'ant-design-vue/es';
import 'ant-design-vue/es/button/style/css';
const _sfc_main = {}

并且_resolveComponent 替换成 __unplugin_components_0

这就将 a-button 组件的全局使用,转换成了按需引入的方式


局限性


unplugin-auto-import 看起来非常厉害,但它也有些局限性:

  • 不能作用于 JSX,因为插件只处理 template 模板的代码。不过JSX 则需要配合 unplugin-auto-import(用于自动引入变量)
  • 在 Vite 中 CSS 无法 tree shaking,不过这个是 Vite 的问题。但 JS 仍然是可以 tree shaking,相对于全局注册组件,对构建产物体积的优化还是非常可观的

总结


使用 unplugin-vue-components 可以非常方便地实现按需引入组件的功能,从而减小项目体积、加快项目加载速度,提升用户体验。

它通过正则匹配 Vue 的全局组件(编译后使用 _resolveComponent 包裹),然后引入组件并替换 _resolveComponent,因此这种方式,只适用于 template 模板编译后的代码,JSX 的自动引入,则需要配合 unplugin-auto-import(用于自动引入变量)

实际上, unplugin-vue-components 还能自动引入项目 components 目录下的组件,同时也支持自定义指定的自动按需引入,更多内容请查看  unplugin-vue-components文档

如果这篇文章对您有所帮助,可以点赞加收藏👍,您的鼓励是我创作路上的最大的动力。也可以关注我的公众号订阅后续的文章:Candy 的修仙秘籍(点击可跳转)

另外,想要米哈游/腾讯内推的,也可以关注公众号找我内推

目录
相关文章
|
3天前
|
JavaScript
Vue3中props的原理与使用
Vue3中props的原理与使用
9 0
|
3天前
|
JavaScript 前端开发
vue中nextTick使用以及原理
vue中nextTick使用以及原理
6 0
|
17天前
|
JavaScript UED
【vue】iview组件 DatePicker 日期选择器如何显示默认当前日期
【vue】iview组件 DatePicker 日期选择器如何显示默认当前日期
25 1
|
2天前
|
JavaScript
Vue实战-将通用组件注册为全局组件
Vue实战-将通用组件注册为全局组件
5 0
|
2天前
|
JavaScript 前端开发
深入了解前端框架Vue.js的响应式原理
本文将深入探讨Vue.js前端框架的核心特性之一——响应式原理。通过分析Vue.js中的数据绑定、依赖追踪和虚拟DOM等机制,读者将对Vue.js的响应式系统有更深入的理解,从而能够更好地利用Vue.js构建灵活、高效的前端应用。
|
3天前
|
编译器
vue3组件TS类型声明实例代码
vue3组件TS类型声明实例代码
5 0
|
3天前
|
JavaScript 前端开发 IDE
vue3基础: 组件注册
vue3基础: 组件注册
11 0
|
3天前
|
JavaScript
vue3使用element-plus 树组件(el-tree)数据回显
vue3使用element-plus 树组件(el-tree)数据回显
6 0
|
4天前
|
缓存 JavaScript
在 Vue 组件中使用计算属性和侦听器来响应路由变化
Vue Router 中,计算属性和侦听器常用于根据路由变化更新组件状态。计算属性缓存依赖,当路由参数改变时自动更新,如示例中的 `userId`。侦听器则监听 `$route` 变化,执行相应操作,例如在 `currentUserId` 示例中响应 `userId` 更新。计算属性适合简单变化,而异步操作或复杂场景可选用侦听器。Vue 3 中,`watchEffect` 减少了部分侦听场景的复杂性。总之,它们用于组件内部响应路由变化,而非直接处理路由逻辑。
12 4
|
5天前
|
JavaScript
Vue3的 组件事件
Vue3的 组件事件
17 0