Vue3+Vant打包報錯 Identifier ‘bem‘ has already been declared的問題排查與解決
前言
在實際項目開發(fā)中,前端構建的坑經常出現在一些意想不到的地方。這次我在做 Vue3 + Vant 項目打包的時候,遇到了一個讓人摸不著頭腦的報錯:
[vite:legacy-post-process] unknown: Identifier 'bem' has already been declared
按理說這是個語法錯誤,但奇怪的是項目本地開發(fā)完全沒問題,只有在 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,發(fā)現編譯結果里有重復的 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 鎖定到 最新的穩(wěn)定版本,并清理 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 插件要謹慎使用:如果目標用戶瀏覽器環(huán)境允許,可以考慮不引入 legacy,以避免構建復雜化。
- 遇到奇怪語法報錯,直接翻 dist 代碼:通常能看到沖突的根源。
總結
Vue3 + Vant 項目打包時報 Identifier 'bem' has already been declared,多數是由于 組件引入重復 或 插件版本不兼容。
解決方式是統(tǒng)一引入方式(推薦 unplugin-vue-components)、升級到最新 Vant 版本、必要時調整 legacy 配置。
這類問題雖然定位過程比較繞,但一旦搞清楚構建流程,就能快速解決。
到此這篇關于Vue3+Vant打包報錯 Identifier ‘bem‘ has already been declared的問題排查與解決的文章就介紹到這了,更多相關Vue3 Vant打包報錯解決內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
element?ui?el-calendar日歷組件使用方法總結
這篇文章主要給大家介紹了關于element?ui?el-calendar日歷組件使用方法的相關資料,elementui是一款基于Vue.js的UI框架,其中的日歷組件calendar是elementui中非常常用的組件之一,需要的朋友可以參考下2023-07-07
Vue3 elementUI 中 date-picker 使用過程遇到坑
這篇文章主要介紹了Vue3 elementUI 中 date-picker 使用過程遇到坑,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2023-10-10
vue?beforeDestroy?clearInterval清除定時器失效的解決
這篇文章主要介紹了vue?beforeDestroy?clearInterval清除定時器失效的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06

