Vue3+Vant打包报错 Identifier ‘bem‘ has already been declared的问题排查与解决

 更新时间:2025年09月19日 08:59:47   作者:网罗开发  
在实际项目开发中,前端构建的坑经常出现在一些意想不到的地方,这次就出现了Vue3+Vant打包时报错Identifier ‘bem‘ has already been declared,下面我们就来看看具体解决方法吧

前言

在实际项目开发中,前端构建的坑经常出现在一些意想不到的地方。这次我在做 Vue3 + Vant 项目打包的时候,遇到了一个让人摸不着头脑的报错:

[vite:legacy-post-process] unknown: Identifier 'bem' has already been declared

按理说这是个语法错误,但奇怪的是项目本地开发完全没问题,只有在 vite build 打包时才会报错。这里我记录下完整的排查和解决过程,也分享一些在工程化场景下的经验。

问题复现

我项目的基本依赖如下:

{
  "dependencies": {
    "vue": "^3.3.4",
    "vant": "^4.8.0"
  },
  "devDependencies": {
    "vite": "^5.0.0",
    "@vitejs/plugin-vue": "^5.0.0",
    "@vitejs/plugin-legacy": "^5.4.0"
  }
}

代码中使用了 Vant 按需引入,配置方式如下:

// vite.config.ts
import { defineConfig } from "vite"
import vue from "@vitejs/plugin-vue"
import legacy from "@vitejs/plugin-legacy"
import Components from "unplugin-vue-components/vite"
import { VantResolver } from "unplugin-vue-components/resolvers"

export default defineConfig({
  plugins: [
    vue(),
    Components({
      resolvers: [VantResolver()],
    }),
    legacy({
      targets: ["defaults", "not IE 11"],
    }),
  ],
})

运行 npm run dev 一切正常,UI 渲染没问题。但一旦 npm run build,就抛出:

[vite:legacy-post-process] unknown: Identifier 'bem' has already been declared

而且注释掉 legacy 插件,依然会报错。

排查过程

1.怀疑是 Vant 内部工具函数冲突

Vant 内部实现里确实有一个 bem 方法,用来生成 CSS BEM className。但按理说不会暴露到全局,也不该和我们项目的变量冲突。

2.定位到编译产物

我在打包后的 .vite 缓存和 dist 下代码里搜索 bem,发现编译结果里有重复的 const bem = ... 定义,说明某些模块在打包时被重复引入,导致语法层面报错。

3.怀疑 unplugin-vue-components 插件引入方式

如果 unplugin-vue-components 插件没有正确配置 resolvers,有可能导致 Vant 组件被同时按需引入和全量引入,进而重复打包。

4.对比官方文档

Vant 官方建议 Vite 项目用 unplugin-vue-components + unplugin-auto-import,而且要保证 Vant 只走一套导入机制。

解决方案

最终我通过以下几个步骤解决了问题:

1. 确认 Vant 引入方式唯一

先检查自己代码里有没有手动 import { Button } from 'vant' 或者 import 'vant/lib/index.css'。如果有,可能会和 unplugin-vue-components 插件的自动导入冲突。

最终只保留插件方式:

// vite.config.ts
import Components from "unplugin-vue-components/vite"
import { VantResolver } from "unplugin-vue-components/resolvers"

Components({
  resolvers: [VantResolver()],
})

代码中直接写:

<template>
  <van-button type="primary">确认</van-button>
</template>

不再写任何 import。

2. 排查 legacy 插件冲突

虽然注释掉 legacy 还是报错,但在我的场景里,legacy 会进一步放大 polyfill 和语法转换的问题。我尝试了 升级 legacy 插件 并修改配置:

legacy({
  targets: ["defaults", "not IE 11"],
  additionalLegacyPolyfills: ["regenerator-runtime/runtime"], // 补充必要 polyfill
})

这样可以避免某些全局 polyfill 影响。

3. 锁定依赖版本

因为 bem 冲突和 Vant 内部实现相关,我最终把 Vant 锁定到 最新的稳定版本,并清理 node_modules 重新安装:

rm -rf node_modules package-lock.json pnpm-lock.yaml
npm install

我的最终依赖:

"vant": "4.8.5",
"unplugin-vue-components": "^0.25.2",

可运行 Demo

这是一个最小可复现的 Demo 配置:

npm init vite@latest vite-vant-demo
cd vite-vant-demo
npm install
npm install vant unplugin-vue-components unplugin-auto-import

vite.config.ts 配置:

import { defineConfig } from "vite"
import vue from "@vitejs/plugin-vue"
import Components from "unplugin-vue-components/vite"
import { VantResolver } from "unplugin-vue-components/resolvers"

export default defineConfig({
  plugins: [
    vue(),
    Components({
      resolvers: [VantResolver()],
    }),
  ],
})

App.vue:

<template>
  <van-button type="primary">确认</van-button>
</template>

运行 npm run build,就不会再出现 Identifier 'bem' has already been declared 的报错。

实际场景的启示

这个问题表面看是 “语法错误”,但实质是 重复依赖和编译冲突。我总结几点经验:

  • 依赖引入保持单一来源:按需引入就不要再手动 import,否则容易重复打包。
  • 插件版本要匹配:Vite 插件、Vant、unplugin-vue-components 要保持在相互兼容的版本。
  • legacy 插件要谨慎使用:如果目标用户浏览器环境允许,可以考虑不引入 legacy,以避免构建复杂化。
  • 遇到奇怪语法报错,直接翻 dist 代码:通常能看到冲突的根源。

总结

Vue3 + Vant 项目打包时报 Identifier 'bem' has already been declared,多数是由于 组件引入重复插件版本不兼容
解决方式是统一引入方式(推荐 unplugin-vue-components)、升级到最新 Vant 版本、必要时调整 legacy 配置。

这类问题虽然定位过程比较绕,但一旦搞清楚构建流程,就能快速解决。

到此这篇关于Vue3+Vant打包报错 Identifier ‘bem‘ has already been declared的问题排查与解决的文章就介绍到这了,更多相关Vue3 Vant打包报错解决内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue3动态加载对话框的方法实例

    vue3动态加载对话框的方法实例

    对话框是很常用的组件,在很多地方都会用到,下面这篇文章主要给大家介绍了关于vue3动态加载对话框的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-03-03
  • element ui el-calendar日历组件使用方法总结

    element ui el-calendar日历组件使用方法总结

    这篇文章主要给大家介绍了关于element ui el-calendar日历组件使用方法的相关资料,elementui是一款基于Vue.js的UI框架,其中的日历组件calendar是elementui中非常常用的组件之一,需要的朋友可以参考下
    2023-07-07
  • vue uniapp 防止按钮多次点击的三种实现方式

    vue uniapp 防止按钮多次点击的三种实现方式

    最近的项目完成后,在性能优化阶段需要做按钮的防止重复点击功能,本文主要介绍了vue uniapp 防止按钮多次点击的三种实现方式,具有一定的参考价值,感兴趣的可以了解一下
    2023-08-08
  • VUE中v-on:click事件中获取当前dom元素的代码

    VUE中v-on:click事件中获取当前dom元素的代码

    这篇文章主要介绍了VUE中v-on:click事件中获取当前dom元素的代码,文中同时给大家提到了v-on:click获取当前事件对象元素的方法,需要的朋友可以参考下
    2018-08-08
  • Vue科学计数法常见处理方法举例

    Vue科学计数法常见处理方法举例

    这篇文章主要给大家介绍了关于Vue科学计数法常见处理方法的相关资料,科学计数法是科学家用来表示很大或很小的数字的一种方便的方法,文中给出了详细的代码示例,需要的朋友可以参考下
    2024-02-02
  • Vue中子组件向父组件传值$emit、.sync的案例详解

    Vue中子组件向父组件传值$emit、.sync的案例详解

    这篇文章主要介绍了Vue中子组件向父组件传值$emit、.sync的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09
  • Vue 删除和增加自定义组件实战教程

    Vue 删除和增加自定义组件实战教程

    Vue.js是一种流行的JavaScript框架,用于构建交互式的Web应用程序,在Vue.js中,我们可以通过动态地增加和删除组件来实现动态页面的构建和更新,本文介绍Vue 删除和增加自定义组件实战教程,感兴趣的朋友一起看看吧
    2024-08-08
  • Vue3 elementUI 中 date-picker 使用过程遇到坑

    Vue3 elementUI 中 date-picker 使用过程遇到坑

    这篇文章主要介绍了Vue3 elementUI 中 date-picker 使用过程遇到坑,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2023-10-10
  • vue项目中请求数据特别多导致页面卡死的解决

    vue项目中请求数据特别多导致页面卡死的解决

    这篇文章主要介绍了vue项目中请求数据特别多导致页面卡死的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • vue beforeDestroy clearInterval清除定时器失效的解决

    vue beforeDestroy clearInterval清除定时器失效的解决

    这篇文章主要介绍了vue beforeDestroy clearInterval清除定时器失效的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06

最新评论