原先是使用 hash mode ,後來因為某個需求要改成 history mode ,但一直遇到一個問題,就是在任何頁面只要使用重新整理,就會出現 404 Not Found 找不到頁面訊息。
在經過許多交叉測試後,發現在 quasar.config.js 中有設定 proxy ,這意味著所有到 '/'
的請求都會被代理到 process.env.API_URL
。
devServer: {
https: false,
port: 8080,
open: true, // opens browser window automatically
proxy: {
'/': {
target: process.env.API_URL,
changeOrigin: true,
pathRewrite: {'^/': ''},
},
},
},
當你使用 Vue Router 的 history
模式時,如果你直接訪問或刷新一個非根路徑(例如 /user
),那麼這個請求會被代理到你的 API 伺服器,而不是被你的開發伺服器處理並返回 index.html
文件。這就是為什麼你會看到 404 錯誤。
要解決這個問題,你需要修改你的代理配置,讓 API 請求和前端路由請求分開。你可以將 API 請求代理到一個特定的路徑,例如 '/api'
,然後在你的應用程式中相應地修改 API 請求的 URL。這樣,只有到 '/api'
的請求會被代理到你的 API 伺服器,其他的請求(例如前端路由)將被你的開發伺服器處理。
那為什麼 hash mode 不會?
在 hash 模式下,URL 的路徑(path)並不會真正發送到伺服器,只有 hash 之前的部分會被發送。hash 之後的部分(例如 #/user
中的 /user
)只會在前端被使用,並不會影響到代理設定。
例如,如果你的應用程式在 hash 模式下,並且發出一個到 #/api/user
的請求,那麼實際上只有 #
之前的部分(也就是 /
)會被發送到伺服器。因此,你的代理設定將會將這個請求代理到 process.env.API_URL
。
所以要將 proxy 調整為如下:
devServer: {
https: false,
port: 8080,
open: true, // opens browser window automatically
proxy: {
'/api': {
target: process.env.API_URL,
changeOrigin: true,
pathRewrite: {'^/api': ''},
},
},
},
'/api'
: 這是一個匹配規則,表示所有以'/api'
開頭的請求都將被代理。target: process.env.API_URL
: 這表示所有匹配的請求將被代理到process.env.API_URL
。(process.env.API_URL
是一個環境變數 .env 檔)changeOrigin: true
: 這表示將會改變原始主機的頭部來源到目標URL。pathRewrite: {'^/api': ''}
: 這表示在請求被代理到目標伺服器之前,URL 中的'/api'
將被替換為空字串。
改完後要記得也要確認一下, API 請求的 URL,將所有的 API 請求 URL 都加上 '/api'
前綴。例如,如果你之前是這樣發出 API 請求的:
axios.get('/user');
你需要改為:
axios.get('/api/user');
或直接調整源頭 baseURL:
const axiosInstance = axios.create({
baseURL: process.env.NODE_ENV === 'development' ?
'/api' :
process.env.API_URL,
withCredentials: true,
headers: {
'crossDomain': true,
'Content-Type': 'application/json',
},
});
proxy 轉換範例:
假設你的環境變數 process.env.API_URL
的值為 'http://my-api-server.com'
,並且你的應用程式發出一個到 /api/user
的請求。
由於你的代理設定是將所有以 /api
開頭的請求都代理到 process.env.API_URL
,這個請求將被代理到 'http://my-api-server.com'
。
然後,pathRewrite
的設定 '{'^/api': ''}'
將會將請求 URL 中的 /api
替換為空字串。因此,最終的請求 URL 將會是 'http://my-api-server.com/user'
。
這就是為什麼你需要在 baseUrl
中加上 /api
,並且在 pathRewrite
中將 /api
替換為空字串的原因。這樣可以確保你的請求被正確地代理到你的 API 伺服器。