前後端完全分離下Vue Router history模式的實現

前段時間上線了使用vue全家桶搭建的個人博客,訪問地址爲Civitasv’s blog。採用了前後端完全分離模式,將前端頁面部署到GitHub pages頁面,後端部分部署至阿里雲個人服務器,僅用於提供數據和rest服務接口。之前的是採用hash模式,並無問題,但最近感覺很多#不太美觀,且不利於SEO,因此考慮將其改變爲history模式,遇到了一些問題,特此記錄分享。

0 簡述vue路由history模式原理

首先,要理解爲了構建SPA應用,需要引入vue前端路由系統,其目的在於改變視圖不向服務器發送請求,也就是說,向服務器發送頁面請求事實上只有最開始的一次,其餘的頁面均依賴前端路由動態改變引入的資源文件實現。

在實現上述功能時,vue路由history模式利用了H5新增的pushState()replaceState()接口方法,它們分別可以添加和修改歷史記錄條目。這些方法通常與window.onpopstate 配合使用。假設在http://starss.me上中執行history.pushState(null, null, "home"),瀏覽器地址會變爲http://starss.me/home/,但頁面不會刷新,也即不會向服務器發送請求,接着vue router就對該url進行處理,實現無刷新頁面變化。

1 404問題

vue官方文檔和很多博客均提到history模式下應該提供後臺支持.

當你使用 history 模式時,URL 就像正常的 url,例如 http://yoursite.com/user/id,也好看!

不過這種模式要玩好,還需要後臺配置支持。因爲我們的應用是個單頁客戶端應用,如果後臺沒有正確的配置,當用戶在瀏覽器直接訪問 http://oursite.com/user/id 就會返回 404,這就不好看了。

HTML history模式

首先解釋下爲什麼會出現404,如果在http://starss.me/下存在你的主頁即index.html,假如在hash模式下手動輸入/刷新了這樣一個url鏈接:

http://starss.me/#/home

則在請求服務器時,會自動去掉#之後的內容,因此服務器會去http://starss.me下尋找index.html,成功後返回頁面,改變路由後,通過vue路由配置找到對應的資源即可。但如果我們將其改變爲history模式之後,再次手動輸入/刷新下面鏈接:

http://starss.me/home

這樣服務器顯然會去http://starss.me/home下尋找主頁資源,自然不可能找到,因此一定會出現404錯誤了。

這也即是官網中說到:“要在服務端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態資源,則應該返回同一個 index.html 頁面”的原因了。這個目的就是在無法匹配資源時,手動配置返回一個應當返回的資源,這個資源也就是我們的主頁了,接着vue router就會解析出路由地址,然後根據自己的配置信息找到對應的資源了。

同樣的原因,在使用GitHub page時,如果index.html只存在於根目錄中,手動輸入/刷新訪問上面的url也會報404錯誤,結合其原理,我想到的解決的思路有兩個:

  1. GitHub page在404時會訪問404.html頁面,因此只需要將index.html備份一份,命名爲404.html即可,放置在根目錄即可,這樣控制檯仍然會報404錯誤,但可以正常顯示;
  2. 對於url : http://starss.me/home,我們還可以新建一個home文件夾,將index.html複製一份至該文件夾,這樣刷新也當然可以訪問到它,而且控制檯也並不會報404錯誤。

我的建議是:

  • 如果路由很少,可以按照第二種方式,對每一個路由均新建一個文件夾,然後複製一份index.html,此時也不需要單獨配置404頁面,GitHub page會給提供(當然也可以配置);

  • 如果路由很多,最好還是按照第一種方式,而且注意這種方式下404.html會被佔用,需要單獨配置404頁面,方法是在路由匹配最下部添加一條即可:

      {
        path: '*',    // 此處需特別注意至於最底部
        name: '404',
        component: () => import('../views/common/404'),
        meta: { title: '404 | Civitasv\'s blog' },
      }
    

按照我的理解,第一種方式其實和前後端不分離模式解決方法思想一致,只是提供一個無法匹配任何已有資源時的候選資源罷了。而第二種可以看作是純前端的解決方式,可以根據項目實際情況選擇使用。

2 二級路由刷新空白問題

這個是路徑的原因,只需要在vue.config.js文件中配置publicPath: "/",即可,事實上,這只是個絕對路徑和相對路徑的問題罷了。

結語

GitHub page鏈接:https://github.com/Civitasv/civitasv.github.io

博客源碼鏈接:https://github.com/Civitasv/blog

如果仍不清楚,可以留言給我,我看到就會回覆

如果喜歡這篇文章,希望你點個贊

and如果有興趣的話,關注公衆號:林木菌,和我一起成長pa~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章