調用其它團隊流量站埋點統計時會截取錨點#,致使單頁應用分頁面流量分析獲取不到數據。而本項目迫切須要按菜單、特殊功能模塊統計流量狀況,等不及流量站的團隊開發升級版,因而選擇改造項目路由爲hostory模式。javascript
SPA,只加載一個HTML,頁面在用戶與應用程序交互時動態更新該頁。即理論上來講,只需加載一次頁面就能夠再也不請求(首屏耗時過長需按模塊chunk,預加載css,按需加載js),當點擊其餘子頁面時只會有相應的URL改變而不會從新加載。css
這種狀況下實現路由的過程分爲兩部分:html
如今主流有2種實現方式:前端
vue-router中提供了三種方式HTML5History(判斷是否支持)、HashHistory、AbstractHistory(用於Node環境,由於不涉及和瀏覽器地址相關記錄關聯在一塊兒;總體流程依舊和 HashHistory 是同樣的,只是這裏經過數組來模擬瀏覽器歷史記錄堆棧信息)vue
默認爲Hash模式,組件(components)映射到路由(routes),registerHook設置守衛入棧,在每次跳轉的時候,遞歸守衛集合,將觸發的守衛進行解析和執行。java
vue-router源碼閱讀webpack
1. Router傳入配置項,設置mode爲'history'ios
export default new Router({ mode: 'history', routes })
2. 開發模式下,webpack 熱啓動配置 history 模式nginx
webpack屬性中historyApiFallback默認能將當前找不到的目錄重定向到主目錄默認index.html。
在 webpack 配置文件的devServer配置,將url重寫到本身配置的目錄:git
// webpack.dev.conf.js devServer: { ... historyApiFallback: { rewrites: [ { from: /.*/, to: '/index.html' } ], }, ... }
3. 部署預發後,刷新時資源404
開發過程一切正常,直到編譯打包發佈。
情況:從域名點擊菜單能正常跳轉,但刷新當前頁會報錯404。(Eg:從test.com點擊訪問/111正常,但直接訪問test.com/111報404)
緣由:在History mode下,直接經過地址欄訪問url會被http server直接解析到該文件路徑,可是spa的路由是虛擬的,並不能直接找到這個file,因此會404。
解決思路:若是URL匹配不到任何靜態資源,就跳轉到默認的index.html,讓router去解析url, nginx中須要配置try_files。
# 當前項目使用了第一級'/'來區分產品,因此這裏匹配metric、stocktake # 通常直接'location ~ /'便可 location ~ ^(/metric|/stocktake) { try_files $uri $uri/ /index.html; }
具體配置官方提供了:其它服務器配置
4. 頁面再也不404,開始報語法錯誤
報錯以下
DOM狀況:
資源狀況:
緣由:修改成history模式後,相對定位再也不適用,資源會根據當前刷新路徑變動訪問路徑(注意上圖資源狀況訪問的文件夾)。在此項目中靜態資源vendor.dll.的引入路徑有問題,需將相對路徑'./'修改成絕對路徑'/'
5. 頁面正常加載,但後端接口被統一重定向
緣由:step3時在nginx處配置了try_files 加上後端接口也是/metric、/stocktake開頭。因而就不幸地被nginx匹配到規則統一做跳轉處理了。
解決:區分接口與頁面。在項目中統一對後端接口加'/api/',nginx新建規則匹配'/api/'並做相應跳轉。
// 在發請求的公共方法處添加'/api/' function ajax(url, type, params, opt = '') { return Q.Promise((resolve, reject) => { const config = { method: type === 'get' ? 'get' : 'post', // TODO: '/api/'暫時做爲nginx區分重定向的匹配字段 待與兆華協商統一 不與路由命名重複 url: C.HOST + '/api/' + url, params: type === 'get' ? params : null, data: configData(type, params, opt) } axios(config).then(checkStatus).then(checkCode).then((response) => { resolve(response) }).catch((err) => { console.log(err) if (err.msg) Notice(err.msg) reject(err) }) }) }
nginx中添加以下匹配規則並重寫url
``` # 後臺三類開頭對應請求不一樣服務器 location ~ ^/api/system/ { rewrite ^/api/(.*) /$1 break; proxy_pass http://assets-api-yf.jd.com; proxy_redirect off; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location ~ ^/api/metric/ { rewrite ^/api/(.*) /$1 break; proxy_pass http://metrics-api-yf2.jd.com; proxy_redirect off; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location ~ ^/api/stocktake/ { rewrite ^/api/(.*) /$1 break; proxy_pass http://meta-api-yf.jd.com; proxy_redirect off; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } ```
6. 切換產品菜單時會刷新
由於使用的是window.location,替換成this.$router.push便可
7. 非法輸入路由時,未正常重定向到首頁,直接404
情況:地址欄輸入test.com/ffsdfdsge,顯示'404 Not Found',並未重定向到首頁。
解決:nginx配置error_page。
server { ... error_page 404 /index.html; ... }
前端小菜鳥一枚,如表述有誤,懇請各位大神指正~