vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > Vue3 Vant打包报错解决

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

作者:网罗开发

在实际项目开发中,前端构建的坑经常出现在一些意想不到的地方,这次就出现了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 的报错。

实际场景的启示

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

总结

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

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

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

您可能感兴趣的文章:
阅读全文