Vue组件库实现按需引入可以这么做

本文为Varlet组件库源码主题阅读系列第七篇,读完本篇,可以了解到如何通过unplugin-vue-components插件来为你的组件库实现按需引入。

手动引入

前面的文章中我们介绍过Varlet组件库的打包流程,最后会打包成几种格式,其中modulecommonjs格式都不会把所有组件的代码打包到同一个文件,而是保留着各个组件的独立,每个组件都导出作为一个Vue插件。

第一种按需使用的方法是我们手动导入某个组件并进行注册:

import {
   
    createApp } from 'vue'
import {
   
    Button } from '@varlet/ui'
import '@varlet/ui/es/button/style/index.js'

createApp().use(Button)

Button组件并不是从它的自身目录中引入的,而是从一个统一的入口,@varlet/ui包的package.json中配置了两个导出入口:

按需引入,也可以理解成是tree shaking,它依赖于ES6模块,因为ESM模块语法是静态的,和运行时无关,只能顶层出现,这就可以只分析导入和导出,不运行代码即可知道模块导出的哪些被使用了哪些没有,没有用到的就可以被删除。

所以想要支持按需引入那么必然使用的是module入口,这个字段目前各种构建工具应该都是支持的,module入口它是个统一的入口,这个文件中显然导出了所有组件,那么比如我们只导出Button组件,其他没有用到的组件最终是不是不会被打包进去呢,实际上并没有这么简单,因为有的文件它会存在副作用,比如修改了原型链、设置了全局变量等,所以虽然没有显式的被使用,但是只要引入了该文件,副作用就生效了,所以不能被删除,要解决这个问题需要在package.json中再配置一个sideEffects字段,指明哪些文件是存在副作用的,没有指明的就是没有副作用的,那么构建工具就可以放心的删除了:

可以看到Varlet告诉了构建工具,这些样式文件是有副作用的,不要给删除了,其他文件中没有用到的模块可以尽情删除。

自动引入

如果你觉得前面的手动引入比较麻烦,Varlet也支持自动引入,这个实现依赖的是unplugin-vue-components插件,这个插件会扫描所有声明在模板中的组件,然后自动引入 组件逻辑样式文件注册组件

Vite中的配置方式:

import vue from '@vitejs/plugin-vue'
import components from 'unplugin-vue-components/vite'
import {
   
    VarletUIResolver } from 'unplugin-vue-components/resolvers'
import {
   
    defineConfig } from 'vite'

export default defineConfig({
   
   
  plugins: [
    vue(),
    components({
   
   
      resolvers: [VarletUIResolver()]
    })
  ]
})

如果想要这个插件支持你的组件库,需要编写一个解析器,也就是类似上面的VarletUIResolver,如果想要给更多人用就需要提个pr,这个插件目前已经支持如下这些流行的组件库:

VarletUIResolver为例来看一下这个解析器都做了什么:

// unplugin-vue-components/src/core/resolvers/varlet-ui.ts
const varDirectives = ['Ripple', 'Lazy']

export function VarletUIResolver(options: VarletUIResolverOptions = {
   
   }): ComponentResolver[] {
   
   
  return [
    {
   
   
      type: 'component',
      resolve: (name: string) => {
   
   
        const {
   
    autoImport = false } = options

        if (autoImport && varFunctions.includes(name))
          return getResolved(name, options)

        if (name.startsWith('Var'))
          return getResolved(name.slice(3), options)
      },
    },
    {
   
   
      type: 'directive',
      resolve: (name: string) => {
   
   
        const {
   
    directives = true } = options

        if (!directives)
          return

        if (!varDirectives.includes(name))
          return

        return getResolved(name, options)
      },
    },
  ]
}

执行VarletUIResolver方法会返回一个数组,unplugin-vue-components支持自动导入组件和指令,所以可以看到上面返回了两种解析方法,虽然目前我们没有看到unplugin-vue-components的源码,但是我们可以猜想unplugin-vue-components在模板中扫描到某个组件时会调用typecomponentresolve,扫描到指令时会调用typedirectiveresolve,如果解析成功,那么就会自动添加导入语句。

当扫描到的组件名以Var开头或扫描到Varlet的指令时,两个解析方法最后都会调用getResolved方法:

// unplugin-vue-components/src/core/resolvers/varlet-ui.ts
export function getResolved(name: string, options: VarletUIResolverOptions): ComponentResolveResult {
   
   
    const {
   
   
        importStyle = 'css',
        importCss = true,
        importLess,
        autoImport = 
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值