Nginx配置Vue項目Hash/History模式路由跳轉(zhuǎn)錯誤的解決方案
前言
最近在一個實際項目中,前端采用 Vue2,路由模式是 hash,后臺通過 Nginx 部署。我們遇到一個讓人頭疼的問題:訪問子路徑路由 /inv/#/login 時,竟然跳轉(zhuǎn)到了錯誤的頁面。切換成 history 模式后路由倒是正常了,但一刷新頁面,前端資源就加載失敗,提示 MIME 類型錯誤。
這篇文章我會把問題的原因分析清楚,然后結(jié)合 Nginx 配置與 Vue 路由的特性給出可運行的解決方案,順便給出實際案例中的 Demo 配置,方便你參考。
背景:Nginx 配置 + Vue 路由模式
在我們的項目中,存在兩個前端子系統(tǒng):
- 管理端:路徑
/→ 對應(yīng)目錄/data/web/sccmp/ - 組長端:路徑
/inv/→ 對應(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 項目中,路由配置采用的是 hash 模式:
const router = new VueRouter({
mode: 'hash',
routes: [
{ path: '/login', component: Login },
{ path: '/dashboard', component: Dashboard }
]
})
遇到的問題
1.在 hash 模式下訪問組長端 https://xxxx.xx.cppinfo.cn/inv/#/login
頁面居然跳轉(zhuǎn)到管理端的登錄頁,而不是組長端。
2.在 history 模式下刷新頁面
出現(xiàn)錯誤:
Failed to load module script: Expected a JavaScript-or-Wasm module script
but the server responded with a MIME type of "text/html".
簡單說就是 JS 資源請求到了 HTML 文件,Nginx 沒有正確返回對應(yīng)的靜態(tài)資源。
問題出在哪里
這個問題本質(zhì)上分兩層:
1.Hash 模式下路徑混淆
Hash 模式的 URL 是 https://domain/inv/#/login,實際上 Nginx 并不知道 #/login 部分,它只處理 /inv/,而 Vue 的 JS 腳本卻從 / 路徑下去加載資源,導致加載的是管理端的 index.html。
2.History 模式下資源路徑錯誤
在 history 模式下,Vue 的 URL 例如 /inv/login,Nginx 需要把所有未知路徑回退到 /inv/index.html。如果配置不對,就會把資源請求(比如 /inv/js/app.js)錯誤地 fallback 到 HTML,從而導致 MIME type 錯誤。
如何解決
方案一:繼續(xù)使用 Hash 模式(推薦初學者)
如果項目允許繼續(xù)用 hash 模式,需要確保 每個子系統(tǒng)的資源路徑是獨立的,避免加載錯目錄。
在 Vue 的 vue.config.js 中設(shè)置 publicPath:
// vue.config.js
module.exports = {
publicPath: '/inv/', // 對應(yīng)組長端的部署路徑
outputDir: 'dist',
productionSourceMap: false
}
這樣構(gòu)建出來的資源都會掛在 /inv/ 下,避免沖突。
Nginx 保持原配置即可。
方案二:使用 History 模式(推薦最終方案)
History 模式對 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;
# 只針對 html 路由回退
try_files $uri $uri/ /index.html;
}
關(guān)鍵點:
root用而不是alias(如果用 alias,要小心路徑拼接規(guī)則)。try_files中/index.html會 fallback 到當前root的 index.html,而不會錯誤地去加載/下的文件。- 保證靜態(tài)資源路徑正確,例如
/inv/js/app.js請求到/data/web/inv/js/app.js。
實戰(zhàn) Demo 配置(可運行)
假設(shè)我們有兩個 Vue 項目,構(gòu)建產(chǎn)物分別在 /data/web/sccmp/ 和 /data/web/inv/。
Vue 配置 vue.config.js:
// 管理端 vue.config.js
module.exports = {
publicPath: '/',
outputDir: 'dist-admin',
}
// 組長端 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;
}
}
這樣:
- 訪問
http://demo.local/→ 管理端 - 訪問
http://demo.local/inv/→ 組長端 - 刷新任意路由(無論是
/dashboard還是/inv/login)都能正常返回對應(yīng)的 index.html,再由前端接管路由。
總結(jié)
- Hash 模式:簡單,兼容性強,但 URL 不夠美觀。需要在 Vue 構(gòu)建配置里設(shè)置好
publicPath,避免資源路徑錯亂。 - History 模式:更優(yōu)雅,但 Nginx 必須配合
try_files做路由回退,確保靜態(tài)資源不會被錯誤地 fallback 到 index.html。 - 問題本質(zhì):不是 Vue 路由寫錯,而是 Nginx 路徑處理和前端
publicPath沒有對應(yīng)上。
我的建議是:開發(fā)初期可以用 Hash 模式省心,上線前建議切換到 History 模式,并仔細配置好 Nginx。
到此這篇關(guān)于Nginx配置Vue項目Hash/History模式路由跳轉(zhuǎn)錯誤的解決方案的文章就介紹到這了,更多相關(guān)Nginx配置Vue路由模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Nginx服務(wù)器基礎(chǔ)的安全配置與一些安全使用提示
這篇文章主要介紹了Nginx服務(wù)器基礎(chǔ)的安全配置與一些安全使用提示,文中舉了一些典型的Nginx與PHP的環(huán)境用例,需要的朋友可以參考下2016-01-01
nginx的keepalive相關(guān)參數(shù)使用源碼解讀
這篇文章主要為大家介紹了nginx的keepalive相關(guān)參數(shù)使用源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-12-12

