You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue模板中@mdi/js图标动态导入是否支持tree-shaking?

问题根源

你当前的方案无法支持tree-shaking的核心原因是:你在运行时动态导入全量@mdi/js包后通过变量名取值,构建工具(Vite/Webpack/Rollup)在编译阶段无法静态分析你实际用到的图标,只能将整个@mdi/js的所有图标全量打入最终产物。

最优解决方案(保留原有调用习惯,无需手动导入图标)

该方案不需要修改你现有业务代码中<Icon name='mdiMagnify' />的调用方式,仅需新增依赖、调整构建配置和Icon组件实现即可实现全量tree-shaking,仅打包用到的图标。

步骤1:安装依赖

npm install unplugin-icons @iconify-json/mdi -D
# 用yarn/pnpm的话自行替换包管理器命令即可

步骤2:调整构建配置

以Vite为例,修改vite.config.js配置:

import { defineConfig } from 'vite'
import Icons from 'unplugin-icons/vite'

export default defineConfig({
  plugins: [
    // 其他原有插件
    Icons({
      compiler: 'vue2', // Vue3项目改为vue3即可
      autoInstall: false,
    })
  ]
})

如果使用Webpack,仅需将unplugin-icons/vite替换为unplugin-icons/webpack,其余配置逻辑完全一致。

步骤3:重写Icon.vue组件

<template>
  <component :is="iconComponent" v-bind="$attrs" />
</template>

<script>
// Vue3环境需要先导入defineAsyncComponent,Vue2无需该行
// import { defineAsyncComponent } from 'vue'

export default {
  name: 'Icon',
  props: {
    name: {
      required: true,
      type: String,
    },
  },
  computed: {
    iconComponent() {
      // 将mdi开头的驼峰命名转换为短横线命名
      const iconName = this.name
        .replace(/^mdi/, '')
        .replace(/([A-Z])/g, '-$1')
        .toLowerCase()
      return defineAsyncComponent(() => import(`~icons/mdi/${iconName}`))
    },
  },
}
</script>

备选无额外依赖方案

如果不想新增依赖,可以手动维护项目用到的图标列表,让构建工具可以静态分析:

  1. 新建src/utils/icons.js文件,手动导入所有用到的图标:
export { mdiMagnify, mdiMenu, mdiClose } from '@mdi/js'
  1. 修改Icon组件的导入路径为本地文件:
async created() {
  const { [this.name]: icon } = await import('@/utils/icons.js')
  this.icon = icon
}

该方案缺点是每次新增图标都需要手动在icons.js里加导出,优点是不需要新增第三方依赖。


内容的提问来源于stack exchange,提问作者stephenjason

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 21:18:04