Laravel+vue實現history模式URL可行方案

suqj發表於2019-01-19

專案:laravel + vue 實現前後端分離。
vue-router 預設 hash 模式 —— 使用 URL 的 hash 來模擬一個完整的 URL,於是當 URL 改變時,頁面不會重新載入。

  • hash URL 例如:http://yoursite.com/#/user/id
  • history 模式時,URL就像正常的 url,例如 http://yoursite.com/user/id

沒有特別的要求的話,hash模式亦正常訪問。好嘛,產品要求URL要像正常那樣的 —— history模式的。看看vue文件,要實現vue history模式也很簡單。vue 切換一下模式,本地測試ok啦。
接下來,看到還需要後臺配置支援:

因為VUE應用是個單頁客戶端應用,如果後臺沒有正確的配置,當使用者在瀏覽器直接訪問 http://oursite.com/user/id 就會返回 404,這就不好看了。所以呢,你要在服務端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態資源,則應該返回同一個 index.html 頁面,這個頁面就是你 app 依賴的頁面。

So,Nginx配置一下:

location / {
  try_files $uri $uri/ /index.html;
}

沒錯,部署前端資源Nginx伺服器上,簡單加上一條通用匹配規則。
至此,vue 前端搞定了,但是。。。還是不行的!
原因是從前端伺服器訪問是正常了,但是域名指向的是後端伺服器,所以當vue router history模式url直接訪問時還是會404.
當到這裡,又回頭排查一下是不是前面哪裡搞錯了,仔細看下來,沒問題啊,完全按vue文件說明操作啦。
想一陣子,才找到思路:404是後端報出的,也就說Laravel給出的,laravel router 壓根就沒前端定義的路由。所以,當即一拍腦子,就想到是不是將laravel 異常處理在response出去前給中斷一下,將404處理交給前端再處理一下,那麼也只是需要在app/Exceptions/Handlerrender方法加下判斷:

/**
     * Render an exception into an HTTP response.
     *
     * @param  IlluminateHttpRequest  $request
     * @param  Exception  $exception
     * @return IlluminateHttpResponse
     */
    public function render($request, Exception $exception)
    {
        // 解決vue history 地址丟失問題
        if($exception instanceof SymfonyComponentHttpKernelExceptionNotFoundHttpException)
        {
            if ($exception->getStatusCode() == 404) {
                return response()->view(`welcome`);
            }
        }
        return parent::render($request, $exception);
    }

解釋一下:welcome 就是載入了vue CSS和JS,也就是vue依賴檔案。
以上搞定前後端分離,vue history 404 問題!

相關文章