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打包报错解决内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解Vue监听数据变化原理

    详解Vue监听数据变化原理

    本篇文章主要介绍了Vue监听数据变化,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • 在Vue中使用Viser说明(基于AntV-G2可视化引擎)

    在Vue中使用Viser说明(基于AntV-G2可视化引擎)

    这篇文章主要介绍了在Vue中使用Viser说明(基于AntV-G2可视化引擎),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-10-10
  • moment转化时间戳出现Invalid Date的问题及解决

    moment转化时间戳出现Invalid Date的问题及解决

    这篇文章主要介绍了moment转化时间戳出现Invalid Date的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • 如何在vue中使用unocss以及基本使用方法

    如何在vue中使用unocss以及基本使用方法

    这篇文章主要给大家介绍了关于如何在vue中使用unocss以及基本使用方法的相关资料,unocss是一个即时的原子CSS引擎,它可以让你用简短的类名来控制元素的样式,而不需要写复杂的CSS代码,需要的朋友可以参考下
    2023-07-07
  • vue+element项目中过滤输入框特殊字符小结

    vue+element项目中过滤输入框特殊字符小结

    这篇文章主要介绍了vue+element项目中过滤输入框特殊字符小结,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-08-08
  • vue+webrtc(腾讯云) 实现直播功能的实践

    vue+webrtc(腾讯云) 实现直播功能的实践

    本文主要介绍了vue+webrtc(腾讯云) 实现直播功能的实践,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • 详解Vue.js 作用域、slot用法(单个slot、具名slot)

    详解Vue.js 作用域、slot用法(单个slot、具名slot)

    这篇文章主要介绍了Vue.js 作用域、slot用法(单个slot、具名slot),本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-10-10
  • Vue修饰符的使用详解

    Vue修饰符的使用详解

    为了方便大家写代码,Vue给大家提供了很多方便的修饰符,比如我们经常用到的取消冒泡,阻止默认事件等等,这篇文章将给大家分享Vue 中的常用的修饰符
    2022-10-10
  • Vue绘制双Y轴折线柱状图

    Vue绘制双Y轴折线柱状图

    这篇文章主要介绍了Vue绘制双Y轴折线柱状图实例,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • Vue实现数据请求拦截

    Vue实现数据请求拦截

    这篇文章主要为大家详细介绍了Vue实现数据请求拦截,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-10-10

最新评论