<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Vue項目布署后,刷新頁面404的真正原因

          共 6738字,需瀏覽 14分鐘

           ·

          2021-05-11 10:37


          從一篇日記說起

          我是一個小前端,我有寫日記的習慣

          2020年10月17 天氣 晴

          今天天氣不錯,心情也跟著好起來了

          辛辛苦苦加班兩個星期終于完成了產品需求,到了要上線的時候了,嘴里也不知不覺哼起了“勞資今晚不加班”的小曲

          一頓操作猛如虎,終端執(zhí)行 npm run build 一把梭,將構建產出的 dist 文件夾扔給了發(fā)際線愈發(fā)上移的后端同學,讓其幫忙布署到服務器上

          不一會,后端同學說項目布署好了,并扔回給了我一個線上鏈接

          懷著激動的心,用顫抖的手慌忙點開,我沒有放過頁面上的每一個細節(jié),畢竟都是用自己的頭發(fā)換回來的,頁面的上每一個按鈕我都要復點一次以確保它們沒有問題,幾分鐘后,我的臉上慢慢洋溢出來了笑容,因為我認為這是一次完美的“線上行動”

          趕緊平復了一下心情,在公司項目里 @BOSS,自豪的表示項目已完美上線,BOSS 們可以驗收

          ~ Wow! 平常高冷女神范的運營小姐姐給我發(fā)消息了,哈哈,一定是要夸我寫的這個系統(tǒng)太好用了吧,點開

          趕緊自己試了試,只要一刷新還真是這樣,今天又得加班了!

          為什么會出現(xiàn)404

          我們先來看一下我們給到后端的dist文件

          可以看到dist下只有一個 index.html 文件及一些靜態(tài)資源,這個是因為Vue是單頁應用(SPA),只有一個index.html作為入口文件,其它的路由都是通過JS來進行跳轉

          接著我們再來分析一下后端 nginx 的配置

          server {
            // 監(jiān)聽80端口
            listen 80;
            // 定義你的站點名稱
            server_name website.com;
            // 根據(jù)請求 URI 設置配置
            location / {
                // 站點根目錄,這里為 vue 構建出來的 dist 目錄
                root   /www/dist;
                // 站點初始頁為index.html 或 index.htm
                index  index.html index.htm;
            }
          }

          我們現(xiàn)在可以根據(jù) nginx 配置得出,當我們在地址欄輸入 website.com 時,這時會打開我們 dist 目錄下的 index.html 文件,然后我們在跳轉路由進入到 website.com/login

          關鍵在這里,當我們在 website.com/login 頁執(zhí)行刷新操作,nginx location 是沒有相關配置的,所以就會出現(xiàn) 404 的情況

          為什么hash模式下沒有問題

          router hash 模式我們都知道是用符號#表示的,如  website.com/#/login, hash 的值為 #/login

          它的特點在于:hash 雖然出現(xiàn)在 URL 中,但不會被包括在 HTTP 請求中,對服務端完全沒有影響,因此改變 hash 不會重新加載頁面

          hash 模式下,僅 hash 符號之前的內容會被包含在請求中,如 website.com/#/login 只有 website.com 會被包含在請求中 ,因此對于服務端來說,即使沒有配置location,也不會返回404錯誤

          單頁應用(SPA)概念

          我們前面有提到單頁應用,那什么是單頁應用呢?

          單頁應用

          單頁應用(single-page application),縮寫SPA 是一種網(wǎng)絡應用程序或網(wǎng)站的模型,它通過動態(tài)重寫當前頁面來與用戶交互,而非傳統(tǒng)的從服務器重新加載整個新頁面。這種方法避免了頁面之間切換打斷用戶體驗,使應用程序更像一個桌面應用程序。在單頁應用中,所有必要的代碼(HTML、JavaScript和CSS)都通過單個頁面的加載而檢索,或者根據(jù)需要(通常是為響應用戶操作)動態(tài)裝載適當?shù)馁Y源并添加到頁面。盡管可以用位置散列或HTML5歷史API來提供應用程序中單獨邏輯頁面的感知和導航能力,但頁面在過程中的任何時間點都不會重新加載,也不會將控制轉移到其他頁面

          大白話來講:

          一個杯子,早上裝的牛奶,中午裝的是開水,晚上裝的是茶,我們可以發(fā)現(xiàn),變的始終是內容,而容器還是那個容器

          當然,每種技術都有其利弊,單頁應用也是如此

          利:

          1. 無刷新體驗,這個應該是最顯著的有點,由于路由分發(fā)直接在瀏覽器端完成,頁面是不刷新,對用戶的響應非常及時,因此提升了用戶體驗

          2. 完全的前端組件化,前端開發(fā)不再以頁面為單位,更多地采用組件化的思想,代碼結構和組織方式更加規(guī)范化,便于修改和調整

          弊:

          1. 首屏較長,要在一個頁面上為用戶提供產品的所有功能,在這個頁面加載的時候,首先要加載大量的靜態(tài)資源,這個加載時間相對比較長

          2. 不利于 SEO,單頁頁面,數(shù)據(jù)在前端渲染,就意味著沒有 SEO,或者需要使用變通的方案

          Router的實現(xiàn)

          為了讓大家加深大家對 Router 的理解,這里我們實現(xiàn)一個最簡潔的 Router

          hash 模式

          核心通過監(jiān)聽url中的hash來進行路由跳轉

          // 定義 Router
          class Router {
              constructor () {
                  this.routes = {}; // 存放路由path及callback
                  this.currentUrl = '';
                  
                  // 監(jiān)聽路由change調用相對應的路由回調
                  window.addEventListener('load'this.refresh, false);
                  window.addEventListener('hashchange'this.refresh, false);
              }
              
              route(path, callback){
                  this.routes[path] = callback;
              }
              
              push(path) {
                  this.routes[path] && this.routes[path]()
              }
          }

          // 使用 router
          window.miniRouter = new Router();
          miniRouter.route('/', () => console.log('page1'))
          miniRouter.route('/page2', () => console.log('page2'))

          miniRouter.push('/'// page1
          miniRouter.push('/page2'// page2

          history 模式

          history 模式核心借用 HTML5 history api,api 提供了豐富的 router 相關屬性

          先了解一個幾個相關的api

          • history.pushState 瀏覽器歷史紀錄添加記錄
          • history.replaceState 修改瀏覽器歷史紀錄中當前紀錄
          • history.popState 當 history 發(fā)生變化時觸發(fā)
          // 定義 Router
          class Router {
              constructor () {
                  this.routes = {};
                  this.listerPopState()
              }
              
              init(path) {
                  history.replaceState({path: path}, null, path);
                  this.routes[path] && this.routes[path]();
              }
              
              route(path, callback){
                  this.routes[path] = callback;
              }
              
              push(path) {
                  history.pushState({path: path}, null, path);
                  this.routes[path] && this.routes[path]();
              }
              
              listerPopState () {
                  window.addEventListener('popstate' , e => {
                      const path = e.state && e.state.path;
                      this.routers[path] && this.routers[path]()
                  })
              }
          }

          // 使用 Router

          window.miniRouter = new Router();
          miniRouter.route('/', ()=> console.log('page1'))
          miniRouter.route('/page2', ()=> console.log('page2'))

          // 跳轉
          miniRouter.push('/page2')  // page2

          解決404

          看到這里我相信大部分同學都能想到怎么解決問題了,

          產生問題的本質是因為我們的路由是通過JS來執(zhí)行視圖切換的,

          當我們進入到子路由時刷新頁面,web容器沒有相對應的頁面此時會出現(xiàn)404

          所以我們只需要配置將任意頁面都重定向到 index.html,把路由交由前端處理

          還是以 nginx 為例,更多版本的大家可以前往https://router.vuejs.org/zh/guide/essentials/history-mode.html 查看

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

          這里有一個小細節(jié),如果出現(xiàn)真的 404 頁面了呢?比如 website.com/notfound

          因為這么做以后,你的服務器就不再返回 404 錯誤頁面,因為對于所有路徑都會返回 index.html 文件。為了避免這種情況,你應該在 Vue 應用里面覆蓋所有的路由情況,然后在給出一個 404 頁面

          const router = new VueRouter({
            mode'history',
            routes: [
              { path'*'component: NotFoundComponent }
            ]
          })

          ??兩個豬頭是什么意思..




          推薦閱讀




          一文弄懂 CSS 中重要的 BFC(附圖解)

          你真的懂 JavaScript 閉包與高階函數(shù)嗎?

          JS 中強大的操作符,總有幾個你沒聽說過

          最后



          如果你覺得這篇內容對你挺有啟發(fā),我想邀請你幫我三個小忙:

          1. 點個「在看」,讓更多的人也能看到這篇內容(喜歡不點在看,都是耍流氓 -_-)

          2. 歡迎加我微信「 sherlocked_93 」拉你進技術群,長期交流學習...

          3. 關注公眾號「前端下午茶」,持續(xù)為你推送精選好文,也可以加我為好友,隨時聊騷。


          點個在看支持我吧,轉發(fā)就更好了


          瀏覽 78
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  色色色色网 | 久久午夜无码鲁丝片午夜精 | 成人淫色综合网站 | 天天一啪极品御姐 | 日韩一级片在线观看 |