Nginx配置Vue項(xiàng)目Hash/History模式路由跳轉(zhuǎn)錯(cuò)誤的解決方案
前言
最近在一個(gè)實(shí)際項(xiàng)目中,前端采用 Vue2,路由模式是 hash,后臺(tái)通過(guò) Nginx 部署。我們遇到一個(gè)讓人頭疼的問(wèn)題:訪問(wèn)子路徑路由 /inv/#/login 時(shí),竟然跳轉(zhuǎn)到了錯(cuò)誤的頁(yè)面。切換成 history 模式后路由倒是正常了,但一刷新頁(yè)面,前端資源就加載失敗,提示 MIME 類(lèi)型錯(cuò)誤。
這篇文章我會(huì)把問(wèn)題的原因分析清楚,然后結(jié)合 Nginx 配置與 Vue 路由的特性給出可運(yùn)行的解決方案,順便給出實(shí)際案例中的 Demo 配置,方便你參考。
背景:Nginx 配置 + Vue 路由模式
在我們的項(xiàng)目中,存在兩個(gè)前端子系統(tǒng):
- 管理端:路徑
/→ 對(duì)應(yīng)目錄/data/web/sccmp/ - 組長(zhǎng)端:路徑
/inv/→ 對(duì)應(yīng)目錄/data/web/inv/
Nginx 配置如下:
location / {
alias /data/web/sccmp/;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /inv/ {
alias /data/web/inv/;
index index.html index.htm;
try_files $uri $uri/ /inv/index.html;
}
Vue 項(xiàng)目中,路由配置采用的是 hash 模式:
const router = new VueRouter({
mode: 'hash',
routes: [
{ path: '/login', component: Login },
{ path: '/dashboard', component: Dashboard }
]
})
遇到的問(wèn)題
1.在 hash 模式下訪問(wèn)組長(zhǎng)端 https://xxxx.xx.cppinfo.cn/inv/#/login
頁(yè)面居然跳轉(zhuǎn)到管理端的登錄頁(yè),而不是組長(zhǎng)端。
2.在 history 模式下刷新頁(yè)面
出現(xiàn)錯(cuò)誤:
Failed to load module script: Expected a JavaScript-or-Wasm module script
but the server responded with a MIME type of "text/html".
簡(jiǎn)單說(shuō)就是 JS 資源請(qǐng)求到了 HTML 文件,Nginx 沒(méi)有正確返回對(duì)應(yīng)的靜態(tài)資源。
問(wèn)題出在哪里
這個(gè)問(wèn)題本質(zhì)上分兩層:
1.Hash 模式下路徑混淆
Hash 模式的 URL 是 https://domain/inv/#/login,實(shí)際上 Nginx 并不知道 #/login 部分,它只處理 /inv/,而 Vue 的 JS 腳本卻從 / 路徑下去加載資源,導(dǎo)致加載的是管理端的 index.html。
2.History 模式下資源路徑錯(cuò)誤
在 history 模式下,Vue 的 URL 例如 /inv/login,Nginx 需要把所有未知路徑回退到 /inv/index.html。如果配置不對(duì),就會(huì)把資源請(qǐng)求(比如 /inv/js/app.js)錯(cuò)誤地 fallback 到 HTML,從而導(dǎo)致 MIME type 錯(cuò)誤。
如何解決
方案一:繼續(xù)使用 Hash 模式(推薦初學(xué)者)
如果項(xiàng)目允許繼續(xù)用 hash 模式,需要確保 每個(gè)子系統(tǒng)的資源路徑是獨(dú)立的,避免加載錯(cuò)目錄。
在 Vue 的 vue.config.js 中設(shè)置 publicPath:
// vue.config.js
module.exports = {
publicPath: '/inv/', // 對(duì)應(yīng)組長(zhǎng)端的部署路徑
outputDir: 'dist',
productionSourceMap: false
}
這樣構(gòu)建出來(lái)的資源都會(huì)掛在 /inv/ 下,避免沖突。
Nginx 保持原配置即可。
方案二:使用 History 模式(推薦最終方案)
History 模式對(duì) URL 更友好,但需要 Nginx 配置精確區(qū)分資源和路由。
Nginx 修改如下:
location / {
root /data/web/sccmp;
index index.html;
try_files $uri $uri/ /index.html;
}
location /inv/ {
root /data/web/inv;
index index.html;
# 只針對(duì) html 路由回退
try_files $uri $uri/ /index.html;
}
關(guān)鍵點(diǎn):
root用而不是alias(如果用 alias,要小心路徑拼接規(guī)則)。try_files中/index.html會(huì) fallback 到當(dāng)前root的 index.html,而不會(huì)錯(cuò)誤地去加載/下的文件。- 保證靜態(tài)資源路徑正確,例如
/inv/js/app.js請(qǐng)求到/data/web/inv/js/app.js。
實(shí)戰(zhàn) Demo 配置(可運(yùn)行)
假設(shè)我們有兩個(gè) Vue 項(xiàng)目,構(gòu)建產(chǎn)物分別在 /data/web/sccmp/ 和 /data/web/inv/。
Vue 配置 vue.config.js:
// 管理端 vue.config.js
module.exports = {
publicPath: '/',
outputDir: 'dist-admin',
}
// 組長(zhǎng)端 vue.config.js
module.exports = {
publicPath: '/inv/',
outputDir: 'dist-inv',
}
Nginx 配置:
server {
listen 80;
server_name demo.local;
location / {
root /data/web/sccmp;
index index.html;
try_files $uri $uri/ /index.html;
}
location /inv/ {
root /data/web/inv;
index index.html;
try_files $uri $uri/ /index.html;
}
}
這樣:
- 訪問(wèn)
http://demo.local/→ 管理端 - 訪問(wèn)
http://demo.local/inv/→ 組長(zhǎng)端 - 刷新任意路由(無(wú)論是
/dashboard還是/inv/login)都能正常返回對(duì)應(yīng)的 index.html,再由前端接管路由。
總結(jié)
- Hash 模式:簡(jiǎn)單,兼容性強(qiáng),但 URL 不夠美觀。需要在 Vue 構(gòu)建配置里設(shè)置好
publicPath,避免資源路徑錯(cuò)亂。 - History 模式:更優(yōu)雅,但 Nginx 必須配合
try_files做路由回退,確保靜態(tài)資源不會(huì)被錯(cuò)誤地 fallback 到 index.html。 - 問(wèn)題本質(zhì):不是 Vue 路由寫(xiě)錯(cuò),而是 Nginx 路徑處理和前端
publicPath沒(méi)有對(duì)應(yīng)上。
我的建議是:開(kāi)發(fā)初期可以用 Hash 模式省心,上線前建議切換到 History 模式,并仔細(xì)配置好 Nginx。
到此這篇關(guān)于Nginx配置Vue項(xiàng)目Hash/History模式路由跳轉(zhuǎn)錯(cuò)誤的解決方案的文章就介紹到這了,更多相關(guān)Nginx配置Vue路由模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Nginx+Lua+Redis構(gòu)建高并發(fā)Web應(yīng)用
使用Nginx+Lua+Redis來(lái)構(gòu)建高并發(fā)Web應(yīng)用,Curl請(qǐng)求Nginx,Nginx通過(guò)Lua查詢Redis,返回json數(shù)據(jù)。2013-10-10
nginx 部署啟動(dòng)jar包用到的一些命令和流程操作
這篇文章主要介紹了nginx 部署啟動(dòng)jar包用到的一些命令和流程操作,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-11-11
nginx反向代理導(dǎo)致session失效的問(wèn)題解決
這篇文章主要介紹了nginx反向代理導(dǎo)致session失效的問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
Nginx出現(xiàn)403 Forbidden問(wèn)題的常見(jiàn)原因與解決
Nginx 返回 403 Forbidden 錯(cuò)誤通常表示客戶端沒(méi)有權(quán)限訪問(wèn)請(qǐng)求的資源,這種錯(cuò)誤有許多可能的原因,本文將為大家介紹一下常見(jiàn)的原因和對(duì)應(yīng)的解決方法,希望對(duì)大家有所幫助2025-03-03
nginx結(jié)合openssl實(shí)現(xiàn)https的方法
這篇文章主要介紹了基于nginx結(jié)合openssl實(shí)現(xiàn)https的方法,準(zhǔn)備工作大家需要安裝nginx服務(wù),具體操作過(guò)程跟隨小編一起看看吧2021-07-07

