背景
在使用 Vue 3 主項(xiàng)目 + Vue 2 子項(xiàng)目 的微前端架構(gòu)中,我們遇到了一些路由跳轉(zhuǎn)時的問題。具體表現(xiàn)為,點(diǎn)擊跳轉(zhuǎn)時,瀏覽器控制臺會報錯:
SyntaxError: Failed to execute 'replace' on 'Location': 'http://localhost:3333undefined' is not a valid URL.


根據(jù)錯誤堆棧信息,問題發(fā)生在 vue-router.mjs 文件的 changeLocation 函數(shù)中。通過進(jìn)一步分析源碼,我們發(fā)現(xiàn)是由于 currentState.current 為 undefined 導(dǎo)致的錯誤。
問題分析
在 vue-router 的實(shí)現(xiàn)中,history.state 對象的 current 屬性是用來存儲當(dāng)前頁面路徑的。但是,某些情況下,當(dāng) current 屬性未定義時,調(diào)用 replaceState 方法會導(dǎo)致無效的 URL,從而拋出 SyntaxError 錯誤。經(jīng)過調(diào)試,我們確認(rèn)這個問題出現(xiàn)在 Vue 3 主項(xiàng)目與 Vue 2 子項(xiàng)目之間的路由沖突中。
解決辦法
為了避免 current 為 undefined 導(dǎo)致的錯誤,我們可以在 Vue 3 主項(xiàng)目的路由配置中手動為 current 屬性賦值,從而確保跳轉(zhuǎn)時的 URL 是有效的。
解決方案
- 在 Vue 3 主項(xiàng)目的
router/index.js文件中,添加如下代碼,確保每次路由跳轉(zhuǎn)時,current狀態(tài)被正確設(shè)置。
import { assign, isEmpty } from 'lodash-es'
// 這段代碼放到router定義之后
router.beforeEach((to, from, next) => {
if (isEmpty(history.state.current)) {
assign(history.state, { current: from.fullPath })
}
next()
})
代碼解釋
-
isEmpty(history.state.current):檢查history.state.current是否為空(即undefined或null)。 -
assign(history.state, { current: from.fullPath }):如果current為空,則手動將from.fullPath(當(dāng)前路由的完整路徑)賦值給history.state.current,確保跳轉(zhuǎn)時有一個有效的歷史狀態(tài)。 -
next():調(diào)用next()繼續(xù)進(jìn)行路由跳轉(zhuǎn)。
通過這樣的處理,確保每次跳轉(zhuǎn)時都有有效的歷史狀態(tài),從而避免出現(xiàn)無效 URL 的錯誤。
總結(jié)
在 Vue 3 主項(xiàng)目與 Vue 2 子項(xiàng)目共存的微前端架構(gòu)中,路由跳轉(zhuǎn)時出現(xiàn) replaceState 錯誤是由于 history.state.current 未定義引起的。通過在主項(xiàng)目的路由配置中添加簡單的檢查與賦值邏輯,可以有效避免該問題,確保路由跳轉(zhuǎn)的正常進(jìn)行。
你可以查看關(guān)于這個問題的討論:qiankun issue #1361