前言
用過Vue單頁面應用開發的,一定都知道Vue-router
這個路由元件,它支援hash
和history
兩種模式。
HTML5 History 模式
vue-router
預設 hash 模式 —— 使用 URL 的 hash 來模擬一個完整的 URL,於是當 URL 改變時,頁面不會重新載入。
如果不想要很醜的 hash,我們可以用路由的 history 模式,這種模式充分利用 history.pushState
API 來完成 URL 跳轉而無須重新載入頁面。
const router = new VueRouter({
mode: 'history',
routes: [...]
})
當你使用 history 模式時,URL 就像正常的 url,例如 http://yoursite.com/user/id
,也好看!
不過這種模式要玩好,還需要後臺配置支援。因為我們的應用是個單頁客戶端應用,如果後臺沒有正確的配置,當使用者在瀏覽器直接訪問 http://oursite.com/user/id
就會返回 404,這就不好看了。
所以呢,你要在服務端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態資源,則應該返回同一個 index.html
頁面,這個頁面就是你 app 依賴的頁面。
aspnetcore使用Vuerouter history模式如何生產部署
今天我們的目的就是如何使用history
模式,讓url地址更加簡潔美觀,為了更完整的演示,從頭手把手演示一遍。
建立vue專案
首先安裝nodejs
,然後執行下面的npm命令建立vue3專案,跟著提示選擇是或否即可完成專案的建立。本次建立的專案名稱為vue-project
npm init vue@3
建立aspnetcore的webapi專案
如下圖選擇ASP.Net Core WebApi專案,專案名稱為TestHistory
,目錄選擇和上面Vue專案同屬一個資料夾下。
配置History模式
配置前端
在vscode
開啟前端專案,找到router配置
由於這裡建立的是Vue3專案模板,模板自動配置好的vuerouter4,
其實下面這種是一樣的。詳情參考,
const router = new VueRouter({
mode: 'history',
routes: [...]
})
如果要使用hash
模式,則使用createWebHashHistory
函式建立。
配置後端
如果我們的前端和後端用的是同一個域名,也就是部署在同一個目錄下,則應該將前端編譯後的Html頁面使用aspnetcore
的靜態資源進行託管,而不是直接放到根目錄下。
後端首先要新增app.UseStaticFiles();
以支援靜態資源託管,然後建立該中介軟體預設的靜態資原始檔目錄wwwroot
。
部署
將webapi專案釋出到本地
vue專案執行npm run build
編譯前端程式碼,將dist
目錄下的檔案拷貝到到webapi釋出後的wwwroot
目錄下,
IIS新建一個站點,這裡使用8080
埠
別忘記安裝Hosting Bundle
。
如果一切順利,開啟http://localhost:8080
你應該會看到這個頁面。
點選about還會顯示下面這個頁面,而且地址是http://localhost:8080/about
,這不就是history
模式的效果嗎!
什麼都沒做,效果就達到了?
別急的得意,在http://localhost:8080/about
這個地址下,重新整理下網頁試試。
臥槽,404了。
先解釋下為什麼會這樣,當你訪問http://localhost:8080
時由於iis預設是設定了預設文件
當找不到你請求的資源時,它會嘗試檢查目錄下的預設文件是否存在,按先後順序檢查,發現存在index.html
所以就返回瀏覽器了,所以能夠正常顯示;當你點選about時,其實只是觸發了頁面的一個事件,頁面有變化,url也變化了,但瀏覽器壓根重新整理。當你手動重新整理http://localhost:8080/about
時,就向後端發起這個地址的Get請求,很明顯,我們沒有寫任何Controller
來匹配這個路由,wwwroot
目錄下也不存在about/index.html
當然返回404了。
如何配置history模式,而不導致404
Vuerouter官方文件給出了部分後端伺服器的配置方式 後端配置例子
這裡只展示aspnetcore常用的伺服器
nginx
location / {
try_files $uri $uri/ /index.html;
}
Internet Information Services (IIS)
- 安裝 IIS UrlRewrite(opens new window)
- 在你的網站根目錄中建立一個
web.config
檔案,內容如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Handle History Mode and custom 404/500" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
nginx的由於沒有環境,沒有測試,應該沒問題,配置也比較簡單。
iis的根據文件做一遍,UrlRewrite可以理解為是一箇中介軟體,會對請求攔截,對符合規則的url進行路徑重寫,可行。
當然我要做的不是上面的任何一種,因為我們的站點可能會部署到各種各樣的伺服器,每次換伺服器都需要不同的配置來實現,很繁瑣,既然我們aspnetcore擁有強大的中介軟體系統,為什麼不讓aspnetcore來做這件事呢,不再依賴不同伺服器的配置方案,實現一次編碼,到處執行,在之前的文章中有介紹過如何處理404 《ASP.NETCore統一處理404錯誤都有哪些方式?》
那我們就在404的處理邏輯裡實現其實就好了。
直接上程式碼
app.MapFallback(async (context) =>
{
var phpath = Path.Join(app.Environment.WebRootPath, context.Request.Path);
var name = Path.Combine(Path.GetDirectoryName(phpath)!, "index.html");
if (File.Exists(name))
{
context.Response.StatusCode = 200;
await context.Response.SendFileAsync(name);
}
});
1.當進入404處理邏輯時,首先拼接訪問路徑
2.檢查訪問的路徑所屬的資料夾下是否存在index.html
檔案
3.當檔案存在,則修改響應碼,返回該檔案。
4.不存在,什麼也不幹(這裡其實可以做個友好提示頁面)。
重新發布,測試,不管如何重新整理,都能正常顯示了。