背景
這是一個(gè)已有項(xiàng)目,之前 install 后一切正常。但某天我重新拉取倉(cāng)庫(kù)到新目錄,準(zhǔn)備在新倉(cāng)庫(kù)上繼續(xù)開(kāi)發(fā)時(shí),卻發(fā)現(xiàn) build 和運(yùn)行都報(bào)錯(cuò)了。
報(bào)錯(cuò)信息如下:
09:15:03 [vite] Pre-transform error: Failed to resolve entry for package "@vue-office/docx". The package may have incorrect main/module/exports specified in its package.json.
09:15:04 [vite] Internal server error: Failed to resolve entry for package "@vue-office/docx". The package may have incorrect main/module/exports specified in its package.json.
Plugin: vite:import-analysis
File: E:/rag-op-admin-web/src/views/application/create/components/FilePreviewDialog.vue
at packageEntryFailure (file:///E:/rag-op-admin-web/node_modules/.pnpm/vite@5.4.1_@types+node@20.16.1_sass@1.77.8/node_modules/vite/dist/node/chunks/dep-Cy9twKMn.js:46533:15)
at resolvePackageEntry (file:///E:/rag-op-admin-web/node_modules/.pnpm/vite@5.4.1_@types+node@20.16.1_sass@1.77.8/node_modules/vite/dist/node/chunks/dep-Cy9twKMn.js:46530:3)
at tryNodeResolve (file:///E:/rag-op-admin-web/node_modules/.pnpm/vite@5.4.1_@types+node@20.16.1_sass@1.77.8/node_modules/vite/dist/node/chunks/dep-Cy9twKMn.js:46346:16)

或是找不到對(duì)應(yīng)的 CSS 文件。
奇怪的是,舊的項(xiàng)目目錄(一直沒(méi)動(dòng)過(guò))卻能正常運(yùn)行。對(duì)比發(fā)現(xiàn),舊項(xiàng)目的 node_modules/@vue-office/excel/lib/ 目錄下存在 index.js 和 index.css,而新拉的倉(cāng)庫(kù)里卻沒(méi)有這些文件。
明明配置文件沒(méi)改過(guò),node 和 pnpm 版本也在兼容范圍內(nèi),為什么新建的倉(cāng)庫(kù)總是缺少文件呢?
解決辦法
經(jīng)過(guò)排查,最終通過(guò)以下幾個(gè)步驟解決了問(wèn)題。下面分享排查和解決的過(guò)程。
1. 檢查 package.json 中的 ignoredBuiltDependencies
"ignoredBuiltDependencies": [
"@vue-office/docx",
"@vue-office/excel",
"@vue-office/pdf",
"@vue-office/pptx",
"esbuild",
"vue-demi"
]
這是 pnpm 用于在安裝時(shí)忽略某些依賴的構(gòu)建步驟和 postinstall 腳本的配置。由于 @vue-office 的所有包都被列在這里,它們的 postinstall 腳本就被跳過(guò)了。
2. 檢查 .npmrc 文件
enable-pre-post-scripts=false
這個(gè)配置禁用了 npm/pnpm 的 pre 和 post 腳本執(zhí)行。這意味著所有包的 postinstall 腳本都不會(huì)自動(dòng)運(yùn)行,自然也包括 @vue-office 包的 postinstall 腳本。所以要把它改成true
3. 手動(dòng)執(zhí)行 postinstall 腳本
即使檢查了上面兩項(xiàng),我還是沒(méi)能立即解決問(wèn)題。最終我手動(dòng)執(zhí)行了各個(gè)包的 postinstall.js 腳本:
node node_modules/@vue-office/excel/lib/script/postinstall.js
node node_modules/@vue-office/docx/lib/script/postinstall.js
node node_modules/@vue-office/pdf/lib/script/postinstall.js
node node_modules/@vue-office/pptx/lib/script/postinstall.js
執(zhí)行完畢后,再去查看 node_modules/@vue-office/excel/lib/ 目錄,發(fā)現(xiàn) index.js 和 index.css 文件已經(jīng)生成,項(xiàng)目也恢復(fù)正常了。
4. 更徹底的解決方式
手動(dòng)執(zhí)行腳本雖然能臨時(shí)解決問(wèn)題,但下次重新安裝依賴時(shí)又會(huì)丟失。為了避免這種情況,可以:
移除
ignoredBuiltDependencies中的相關(guān)包(如果確實(shí)不需要忽略的話)刪除
.npmrc中的enable-pre-post-scripts=false,或者將其改為true使用 pnpm 的 approve-builds 命令(適用于 pnpm 10.x):
運(yùn)行pnpm approve-builds,然后根據(jù)提示選擇允許這些包的構(gòu)建腳本(注意這是交互式操作,適合手動(dòng)構(gòu)建時(shí)使用)-
在項(xiàng)目級(jí)別創(chuàng)建一個(gè)自定義的 postinstall 腳本,在
package.json的scripts中添加:json
"postinstall": "node node_modules/@vue-office/excel/lib/script/postinstall.js && node node_modules/@vue-office/docx/lib/script/postinstall.js && ..."
分析原因
為什么會(huì)出現(xiàn)這個(gè)問(wèn)題?為什么舊項(xiàng)目沒(méi)問(wèn)題,新拉取的倉(cāng)庫(kù)卻出問(wèn)題?
1. @vue-office 包需要運(yùn)行 postinstall 腳本
@vue-office 是一個(gè)同時(shí)支持 Vue 2 和 Vue 3 的庫(kù)。為了兼容兩個(gè)版本,它在安裝后需要通過(guò) postinstall 腳本自動(dòng)檢測(cè)項(xiàng)目中的 Vue 版本,并將對(duì)應(yīng)版本的代碼復(fù)制到 lib 目錄下(生成 index.js 和 index.css)。
如果 postinstall 沒(méi)有執(zhí)行,lib 目錄下就會(huì)缺少這些文件,導(dǎo)致項(xiàng)目在引入時(shí)報(bào)模塊找不到的錯(cuò)誤。
2. 為什么新拉取的倉(cāng)庫(kù) postinstall 沒(méi)有執(zhí)行?
- pnpm 10.x 引入了新的安全特性,默認(rèn)會(huì)忽略構(gòu)建腳本
- 需要使用
pnpm approve-builds來(lái)批準(zhǔn)這些包的構(gòu)建腳本,但這需要交互式操作 - 或者可以創(chuàng)建一個(gè)自定義的 postinstall 腳本在項(xiàng)目級(jí)別
總結(jié)
遇到類似“模塊找不到”的問(wèn)題,尤其是在重新拉取項(xiàng)目后出現(xiàn),可以按以下思路排查:
-
檢查項(xiàng)目中的
.npmrc和package.json中與腳本執(zhí)行相關(guān)的配置(如enable-pre-post-scripts、ignoredBuiltDependencies)。 - 確認(rèn)依賴包是否需要 postinstall 腳本(查看包的文檔或源碼)。
- 嘗試手動(dòng)執(zhí)行 postinstall 腳本,看是否能生成缺失的文件。
-
考慮 pnpm 版本的安全策略,必要時(shí)使用
pnpm approve-builds或自定義 postinstall 腳本。
通過(guò)以上方法,可以確保項(xiàng)目在任何環(huán)境下都能正確安裝依賴并運(yùn)行。