介绍在 vue/react 项目中常用的一些插件。例如自动引入、按需导入等等…

持续更新中…

unplugin-auto-import

用作模块的自动导入,下面将以 vue 项目为例介绍(v2、v3均可),完整的插件配置项可点击标题链接查看。

安装

pnpm add unplugin-auto-import -D

配置 vite.config.ts or vue.config.js

import { defineConfig } from 'vite';
// const { defineConfig } = require('@vue/cli-service');

import autoImport from 'unplugin-auto-import/vite';
# const autoImport = require('unplugin-auto-import/webpack');

export default defineConfig({
  # ...
  plugins: [
    vue(),
    vueJsx(),
+   autoImport({
+     imports: [
+       'vue',
+       {
+         'vue-router': ['useRouter', 'useRoute'],
+       },
+       {
+         'vue-i18n': ['useI18n'],
+       },
        # {
        #   '@vueuse/core': ['useVModel', 'useVModels', 'useMouse'],
        # },
+     ],
+   })
  ]
});

保存,重新编译启动会在默认路径(/)下自动生成 auto-imports.d.ts 文件,里面包含了自动导入的模块。形如:

/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
export {}
declare global {
  const useAttrs: typeof import('vue')['useAttrs'];
  const useCssModule: typeof import('vue')['useCssModule'];
  const useCssVars: typeof import('vue')['useCssVars'];
  const useMouse: typeof import('@vueuse/core')['useMouse'];
  const useRoute: typeof import('vue-router')['useRoute'];
  const useRouter: typeof import('vue-router')['useRouter'];
  const useSlots: typeof import('vue')['useSlots'];
  // ...
}
// for type re-export
declare global {
  // @ts-ignore
  export type { Component, ComponentPublicInstance, ComputedRef, ... } from 'vue';
}

配置 tsconfig.json

为了让项目能够加载识别模块声明,避免编辑器的校验错误提示(虽然不配置不影响实际功能):

{
  # ...
  "include": [
    # ...
+   "./auto-imports.d.ts"
  ]
}

配置 .eslintrc.js

根据插件官方推荐,在使用 typescript 的时候,关掉 eslint 的部分规则校验:

module.exports = {
  # ...
  rules: {
    # ...
+   'no-undef': 'off',
  }
}

如果还存在校验异常,请移步官方查看推荐配置:https://github.com/unplugin/unplugin-auto-import#eslint

使用

完成上面配置后,在项目里无需引入,即可使用某些模块。对比使用:

# 配置了插件以后,下面的引入语句即可直接省略
- import { defineProps, withDefaults, defineEmits, defineExpose } from 'vue';

withDefaults(
  defineProps<{
    activeId: string;
    onlyReview: boolean;
  }>(),
  {
    activeId: '',
    onlyReview: false,
  },
);

defineEmits<{
  (e: 'select', id: string): void;
  (e: 'delete', ids: string[]): void;
}>();

defineExpose({ handleAddComponent, handleDeleteComponent });

function handleAddComponent() {}
function handleDeleteComponent() {}

有没有觉得方便很多?如果你安装了该插件并正确配置了,但是没有生效,可能是缓存原因,请先删除缓存(/node_modules/.cache),然后重启编辑器,执行 npm run dev.

unplugin-vue-components

页面组件自动引入并注册(自身并未支持按需引入)。该插件内置了 VUE-UI 相关组件库的解析器处理(后续是由组件库自身提供支持),方便在项目中直接使用组件库而无需单独引入注册。

安装

# pnpm add element-plus
pnpm add unplugin-vue-components -D

配置 vite.config.ts or vue.config.js

vite.config.ts 中添加如下配置:

# ...
import Components from 'unplugin-vue-components/vite';
# import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';

export default defineConfig({
  # ...
  plugins: [
    # ...
+    Components({
+      // 配置文件生成的位置
+      dts: 'components.d.ts',
+      // 指定需要自动导入的组件库路径(可以是自定义实现的 'src/components'),配置后,在使用时即可无需再引入到 script
+      // 同时,该路径下的所有组件都会添加到 components.d.ts 的声明中
+      dirs: [],
# +      resolvers: [ElementPlusResolver()],
+      resolvers: [],
+    }),
  ]
})

添加上面配置,在默认的路径(/)下会生成 components.d.ts,形如:

/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
export {}

declare module 'vue' {
  export interface GlobalComponents {
    HelloWorld: typeof import('./src/components/HelloWorld.vue')['default'];
    // ElLink: typeof import('element-plus/es')['ElLink'];
    RouterLink: typeof import('vue-router')['RouterLink'];
    RouterView: typeof import('vue-router')['RouterView'];
  }
}

虽然基于该插件以及解析器的实现,可以完成对三方组件库的组件的自动引入(即不搭配其他插件,此时已经无需在 main.ts 里全局注册或者页面组件内部引入并局部注册),但是并没有做到按需加载…

按需加载

以我在案例中使用的 element-plus 为例,根据官方推荐的方式, 还需要结合 unplugin-auto-import 插件使用,达到按需加载的目的:

# ...
import autoImport from 'unplugin-auto-import/vite';

export default defineConfig({
  # ...
  plugins: [
    # ...
    autoImport({
      # ...
+     resolvers: [ElementPlusResolver()],
    }),
  ]
})

上面的配置是基于高版本的,如果是低版本的 element-plus or element-ui...,可结合组件库自身推荐的方式,例如搭配 babel-plugin-component or babel-plugin-import 实现,下面提供可行性方案:

# vant
pnpm add babel-plugin-import -D
# element-ui
pnpm add babel-plugin-component -D

再添加 babel 配置:

// babel.config.js
module.exports = {
  presets: ['@vue/cli-plugin-babel/preset'],
  plugins: [
    [
      'component',
      {
        libraryName: 'element-ui',
        styleLibraryName: 'theme-chalk',
      },
    ],
    [
      'import',
      {
        libraryName: 'vant',
        libraryDirectory: 'es',
        style: true,
      },
    ],
  ],
};

然后在 unplugin-vue-components 的 Components 配置中添加 ElementUiResolver、VantResolver 即可(自动完成注册)。

配置 tsconfig.json

将生成的 components.d.ts 文件地址放入配置的 includes 中,这样在 vue 组件内使用三方组件时,如果组件库提供有类型支持,此时会有相关prop 类型提示。

{
  # ...
  "include": [
    # ...
+   "./components.d.ts"
  ]
}

使用

完成上述配置,可以在组件内直接使用相关组件:

<script setup lang="ts">
- import { ElLink } from 'element-plus';
- import HelloWorld from './components/HelloWorld.vue'
</script>

<template>
  <HelloWorld msg="You did it!" />
  <el-link type="primary">primary</el-link>
</template>

注意:在使用插件进行自动引入注册时,三方库的样式是后加载的。意味着可能存在自定义样式和组件自身样式优先级的问题。适当为自定义样式添加权重即可。