◆
Vite 中 Vant2 组件库按需加载自定义 Resolver 实现
前言
项目构建工具升级成了
vite,但是出于兼容性要求,使用的vant组件库仍旧为2.x版本。基于
vite构建工具,对vant进行按需加载,现在使用最多的就是unplugin-vue-components插件, 配置也比较简单,如下
import { VantResolver } from 'unplugin-vue-components/resolvers';
import Components from 'unplugin-vue-components/vite';
Components({
dts: resolve(root, './types/components.d.ts'),
resolvers: [VantResolver()],
});
如果没有对打包的文件进行分析,自然就认为 vant 已经按需加载了,事实上,此插件仅对 vant3, vant4 生效, 如果你当前项目使用的是 vant2,打包时仍旧是全量加载。
问题原因
我们看下插件提供的 VantResolver() 源码
import type { ComponentResolver, SideEffectsInfo } from '../../types';
import { isSSR, kebabCase } from '../utils';
const moduleType = isSSR ? 'lib' : 'es';
export interface VantResolverOptions {
/**
* import style css or less along with components
*
* @default true
*/
importStyle?: boolean | 'css' | 'less';
}
function getSideEffects(
dirName: string,
options: VantResolverOptions,
): SideEffectsInfo | undefined {
const { importStyle = true } = options;
if (!importStyle || isSSR) return;
if (importStyle === 'less') return `vant/${moduleType}/${dirName}/style/less`;
if (importStyle === 'css') return `vant/${moduleType}/${dirName}/style/index`;
return `vant/${moduleType}/${dirName}/style/index`;
}
/**
* Resolver for Vant
*
* @link https://github.com/youzan/vant
*/
export function VantResolver(
options: VantResolverOptions = {},
): ComponentResolver {
return {
type: 'component',
resolve: (name: string) => {
if (name.startsWith('Van')) {
const partialName = name.slice(3);
return {
name: partialName,
from: `vant/${moduleType}`,
sideEffects: getSideEffects(kebabCase(partialName), options),
};
}
},
};
}
通过上述代码可以发现,如果你使用了一个 vant 组件如 Button, 那么插件会帮你生成如下代码
import { Button } from 'vant/es';
import 'vant/es/button/style/index';
此配置对于 vant3/4 进行按需加载是生效的,但是对于 vant2 不生效,我们看下 vant2 推荐的按需加载方式
- 使用
babel-plugin-import插件,这是基于webpack开发的,vite要使用这个插件需要大量的其他插件支持 - 手动按需引入组件
import Button from 'vant/lib/button';
import 'vant/lib/button/style';
我们只要通过 unplugin-vue-components 实现上述解析器即可,代码如下
function kebabCase(str) {
if (!str) return '';
str = str.replace(/([A-Z])/g, ' $1').toLowerCase();
str = str.replace(/[\s_]+/g, '-');
str = str.replace(/^-+|-+$/g, '');
str = str.replace(/-+/g, '-');
return str;
}
Components({
resolvers: [
[
(name: string) => {
if (name.startsWith('Van')) {
const partialName = kebabCase(name.slice(3));
return {
from: `vant/lib/${partialName}`,
sideEffects: `vant/lib/${partialName}/style`,
};
}
},
],
],
dts: resolve(root, './types/components.d.ts'),
});
可以看出来我们去掉的 name 参数,因为 vant2 实现按需加载的组件不是解构导出。
对于 vant 暴露的方法
上述对组件实现了按需加载,但是当我们使用其中的方法时,如 Toast 组件, 我们同样去使用 antfu 开发的 unplugin-auto-import,实现一个默认导出的 Toast 方法即可
import AutoImport from 'unplugin-auto-import/vite';
AutoImport({
imports: [
{
'vant/lib/toast': [
['default', 'Toast'], // 将默认导出重命名为 Toast
],
},
],
});
只要使用了插件形式的按需加载,就不要在代码中自己再去引入!否则仍旧会导致全量打包

还没有留言,来发表第一条吧~