Vue3 + Vant 打包报错 Identifier ‘bem‘ has already been declared 的排查与解决
在实际项目开发中,前端构建的坑经常出现在一些意想不到的地方。这次我在做 Vue3 + Vant 项目打包的时候,遇到了一个让人摸不着头脑的报错
大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。
图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG
我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。
展菲:您的前沿技术领航员
👋 大家好,我是展菲!
📱 全网搜索“展菲”,即可纵览我在各大平台的知识足迹。
📣 公众号“Swift社区”,每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。
💬 微信端添加好友“fzhanfei”,与我直接交流,不管是项目瓶颈的求助,还是行业趋势的探讨,随时畅所欲言。
📅 最新动态:2025 年 3 月 17 日
快来加入技术社区,一起挖掘技术的无限潜能,携手迈向数字化新征程!
前言
在实际项目开发中,前端构建的坑经常出现在一些意想不到的地方。这次我在做 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
插件,依然会报错。
排查过程
-
怀疑是 Vant 内部工具函数冲突
Vant 内部实现里确实有一个bem
方法,用来生成 CSS BEM className。但按理说不会暴露到全局,也不该和我们项目的变量冲突。 -
定位到编译产物
我在打包后的.vite
缓存和dist
下代码里搜索bem
,发现编译结果里有重复的const bem = ...
定义,说明某些模块在打包时被重复引入,导致语法层面报错。 -
怀疑 unplugin-vue-components 插件引入方式
如果unplugin-vue-components
插件没有正确配置resolvers
,有可能导致 Vant 组件被同时按需引入和全量引入,进而重复打包。 -
对比官方文档
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 配置。
这类问题虽然定位过程比较绕,但一旦搞清楚构建流程,就能快速解决。
更多推荐
所有评论(0)