Vue Router history模式的配置方法及其原理

轉(zhuǎn)載自:https://segmentfault.com/a/1190000019391139

vue-router分為hash和history模式,前者為其默認(rèn)模式,url的表現(xiàn)形式為http://yoursite.com#home矛缨,比較難看扯饶。后者的url表現(xiàn)形式為http://yoursite.com/home腰湾,比較美觀。

但如果要使用history模式疆股,我們需要在后端進(jìn)行額外配置费坊。本文將討論如何配置以及為什么要這樣配置。

history模式的配置方法

我們來看看官方文檔是教我們怎么配置的:HTML5 History 模式旬痹。

首先要將mode設(shè)置為history:

constrouter =newVueRouter({mode:'history',routes: [...]})

然后設(shè)置后端(這里采用的nginx):

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

然后就......沒了附井!顯然官方的教程講的比較簡略,并且我們參照這個(gè)教程實(shí)際上還是會(huì)遇到一些問題两残。

history模式的配置實(shí)踐及原理

強(qiáng)烈建議:閱讀這部分之前永毅,先看一下nginx的這部分文檔這部分文檔

既然官方文檔教我們這樣做了人弓,我們就按照它說的來實(shí)踐一下沼死。

只配置前端的情況

首先,我們將mode設(shè)置為history票从,但不配置后端漫雕。然后,假如我們的路由是長這個(gè)樣子的:

constroutes = [? ? {path:'/home',component: Home},? ? {path:'/',redirect:'/home'}];

我們用nginx部署項(xiàng)目峰鄙,然后在地址欄輸入http://localhost:8080(這里配置的端口是8080)浸间,你會(huì)發(fā)現(xiàn)地址欄之后會(huì)變?yōu)閔ttp://localhost:8080/home,并且看起來一切正常吟榴,似乎路由也可以正常切換而不會(huì)發(fā)生其他問題(實(shí)際上會(huì)發(fā)生問題魁蒜,后面會(huì)進(jìn)行討論)》苑看起來好像不需要按官網(wǎng)告訴我們的那樣配置后端也能實(shí)現(xiàn)history模式兜看,但如果你直接在地址欄輸入http://localhost:8080/home,你會(huì)發(fā)現(xiàn)你獲得了一個(gè)404頁面狭瞎。

那么http://localhost:8080為什么可以(部分)正常顯示呢细移?道理其實(shí)很簡單,你訪問http://localhost:8080時(shí)熊锭,靜態(tài)服務(wù)器(這里是nginx)會(huì)默認(rèn)去目標(biāo)目錄(這里為location中root所指定的目錄)下尋找index.html(這是nginx在端口后沒有額外路徑時(shí)的默認(rèn)行為)弧轧,目標(biāo)目錄下有這個(gè)文件嗎?有碗殷!然后靜態(tài)服務(wù)器返回給你這個(gè)文件精绎,配合vue-router進(jìn)行轉(zhuǎn)發(fā),自然可以(部分)正常顯示锌妻。

但如果直接訪問http://localhost:8080/home代乃,靜態(tài)服務(wù)器會(huì)去目標(biāo)目錄下尋找home文件,目標(biāo)目錄下有這個(gè)文件嗎仿粹?沒有搁吓!所以自然就404了。

配置后端

為了達(dá)到直接訪問http://localhost:8080/home也可以成功的目的吭历,我們需要對(duì)后端(這里即nginx)進(jìn)行一些配置擎浴。

首先想想,要怎樣才能達(dá)到這個(gè)目的呢毒涧?

在傳統(tǒng)的hash模式中(http://localhost:8080#home)贮预,即使不需要配置,靜態(tài)服務(wù)器始終會(huì)去尋找index.html并返回給我們契讲,然后vue-router會(huì)獲取#后面的字符作為參數(shù)仿吞,對(duì)前端頁面進(jìn)行變換。

類比一下捡偏,在history模式中唤冈,我們所想要的情況就是:輸入http://localhost:8080/home,但最終返回的也是index.html银伟,然后vue-router會(huì)獲取home作為參數(shù)你虹,對(duì)前端頁面進(jìn)行變換绘搞。那么在nginx中,誰能做到這件事呢傅物?答案就是try_files夯辖。

首先看一下try_files的語法:try_files?file ... uri;

然后看一下官方文檔對(duì)它的介紹:

Checks the existence of files in the specified order and uses the first found file for request processing; the processing is performed in the current context. The path to a file is constructed from the file parameter according to the root and alias directives. It is possible to check directory’s existence by specifying a slash at the end of a name, e.g. “$uri/”. If none of the files were found, an internal redirect to the uri specified in the last parameter is made.

大意就是它會(huì)按照try_files后面的參數(shù)依次去匹配root中對(duì)應(yīng)的文件或文件夾。如果匹配到的是一個(gè)文件董饰,那么將返回這個(gè)文件蒿褂;如果匹配到的是一個(gè)文件夾,那么將返回這個(gè)文件夾中index指令指定的文件卒暂。最后一個(gè)uri參數(shù)將作為前面沒有匹配到的fallback啄栓。(注意try_files指令至少需要兩個(gè)參數(shù))

拿我自己的網(wǎng)站舉個(gè)例子:

location/ {root/data/www/rf-blog-web;indexindex.html;try_files$uri $uri/ /index.html; }

$uri是nginx中的變量,比如我訪問的網(wǎng)址是http://localhost:8080/home也祠,那么它就代表的/home昙楚。

在rf-blog-web這個(gè)目錄中,沒有子目錄诈嘿,只有一個(gè)index.html和一些壓縮后的名稱是hash值的.js文件桂肌。當(dāng)我們請(qǐng)求http://localhost:8080/home這個(gè)地址時(shí),首先查找有無home這個(gè)文件永淌,沒有崎场;再查找有無home目錄,也沒有遂蛀。所以最終會(huì)定位到第三個(gè)參數(shù)從而返回index.html谭跨,按照這個(gè)規(guī)則,所有路由里的url路徑最后都會(huì)定位到index.html李滴。vue-router再獲取參數(shù)進(jìn)行前端頁面的變換螃宙,至此,我們已經(jīng)可以通過http://localhost:8080/home這個(gè)地址進(jìn)行成功地訪問了所坯。

而$uri這個(gè)參數(shù)的作用其實(shí)是匹配那些.js文件用的谆扎,而$uri/在這個(gè)例子中并沒有多大用,實(shí)際上是可以去掉的芹助。

history模式下可能會(huì)遇到的問題及解決方案

在將我的項(xiàng)目(在路由中用了懶加載)改為history模式的過程中堂湖,有時(shí)候發(fā)現(xiàn)會(huì)出現(xiàn)chunk加載出錯(cuò)的情況,打開chrome的network發(fā)現(xiàn)那個(gè)chunk加載404了状土,是因?yàn)檎?qǐng)求的url中多了一層路徑无蜂。我在這里發(fā)現(xiàn)了解決方案。

LinusBorg說蒙谓,因?yàn)樵趆istory模式中切換路由時(shí)斥季,我們是真正改變了頁面的url路徑,所以webpack的runtime會(huì)認(rèn)為它位于example.com/some/path累驮。如果publicPath是設(shè)置的相對(duì)路徑酣倾,那么webpack加載chunk時(shí)可能會(huì)變成example.com/some/path/static/js/3.js這樣的路徑舵揭,然而chunk的真正路徑是example.com/static/js/3.js,所以我們需要將publicPath設(shè)置為絕對(duì)路徑(publicPath: '/')來解決這個(gè)問題躁锡。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末午绳,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子稚铣,更是在濱河造成了極大的恐慌,老刑警劉巖墅垮,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惕医,死亡現(xiàn)場離奇詭異,居然都是意外死亡算色,警方通過查閱死者的電腦和手機(jī)抬伺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來灾梦,“玉大人峡钓,你說我怎么就攤上這事∪艉樱” “怎么了能岩?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長萧福。 經(jīng)常有香客問我拉鹃,道長,這世上最難降的妖魔是什么鲫忍? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任膏燕,我火速辦了婚禮,結(jié)果婚禮上悟民,老公的妹妹穿的比我還像新娘坝辫。我一直安慰自己,他們只是感情好射亏,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布近忙。 她就那樣靜靜地躺著,像睡著了一般智润。 火紅的嫁衣襯著肌膚如雪银锻。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天做鹰,我揣著相機(jī)與錄音击纬,去河邊找鬼。 笑死钾麸,一個(gè)胖子當(dāng)著我的面吹牛更振,可吹牛的內(nèi)容都是我干的炕桨。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼肯腕,長吁一口氣:“原來是場噩夢啊……” “哼献宫!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起实撒,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤姊途,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后知态,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捷兰,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年负敏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了贡茅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡其做,死狀恐怖顶考,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情妖泄,我是刑警寧澤驹沿,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站蹈胡,受9級(jí)特大地震影響甚负,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜审残,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一梭域、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧搅轿,春花似錦病涨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至雀鹃,卻和暖如春幻工,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背黎茎。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國打工囊颅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓踢代,卻偏偏與公主長得像盲憎,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子胳挎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容