前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用 unplugin-vue-components 按需引入组件(内附实现原理)

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

作者头像
CandyTong
发布2023-06-18 10:45:34
2K0
发布2023-06-18 10:45:34
举报

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

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

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

代码语言:javascript
复制
import Button from 'ant-design-vue/lib/button';
import 'ant-design-vue/lib/button/style';

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

代码语言:javascript
复制
import { Button } from 'ant-design-vue';

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

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

使用效果

Antd Vuevite 为例:

代码语言:javascript
复制
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 组件以及组件样式,使用起来就像全局组件一样,但这是按需自动引入,可以减少产物大小。

代码语言:javascript
复制
<template>
  <a-button>按钮</a-button>
</template>

这样直接使用即可

解析器

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

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

以对象为例:

代码语言:javascript
复制
{
    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

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

代码语言:javascript
复制
{
  name: 'Button',
  from: 'ant-design-vue/es',
  sideEffects: 'ant-design-vue/es/button/style/css',
}

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

代码语言:javascript
复制
import { Button } from 'ant-design-vue/es'
import 'ant-design-vue/es/button/style/css'

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

代码语言:javascript
复制
import '../../style/default.css';
import './index.css';

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

实现原理

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

代码语言:javascript
复制
<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 编译后的代码[2]:

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

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

代码语言:javascript
复制
{
  name: 'Button',
  from: 'ant-design-vue/es',
  sideEffects: 'ant-design-vue/es/button/style/css',
}

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

引入以下代码:

代码语言:javascript
复制
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[4](用于自动引入变量)
  • • 在 Vite 中 CSS 无法 tree shaking,不过这个是 Vite 的问题。但 JS 仍然是可以 tree shaking,相对于全局注册组件,对构建产物体积的优化还是非常可观的

总结

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

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

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

引用链接

[1] babel-plugin-import: https://github.com/ant-design/babel-plugin-import [2] 编译后的代码: https://sfc.vuejs.org/#eNo9jk0KAjEMha8yZG3bfSkD3iObjlSdwf7QpLoYegDBlQfxWIK3sBWZXfIlfO+tsE9JXosDDYadTxfLbsQwDMaKqTDHML4f98/zZdQGMBi1/cIOZp9iZuFtkgvF0FRrN+D/QAh6+JHOWlbfEc7MibRSdDz0AgvJmE+qTTKXwLN30pEXU443crmJEbqiYqhQv4G3QNY= [3] Vue 官网: https://cn.vuejs.org/api/render-function.html#resolvecomponent [4] unplugin-auto-import: https://github.com/antfu/unplugin-auto-import [5] unplugin-auto-import: https://github.com/antfu/unplugin-auto-import [6] 文档: https://github.com/antfu/unplugin-vue-components

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-03-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Candy 的修仙秘籍 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用效果
  • 解析器
  • 实现原理
  • 局限性
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档