最近在更新個人主頁,這個主題看夠了闪檬,就想換另一個星著。但是今天突然發(fā)現(xiàn)我的 Vue 不能熱更新?費了一會勁才搞明白怎么回事粗悯。下面就分享一下我的入坑虚循,出坑過程吧。
webpack-dev-server 炸了样傍?
一開始我還真的以為是 HMR 不工作了横缔,所以這里陷入了一個大坑,這里省略 1 個小時的搜索铭乾。剪廉。。
后面細心我的發(fā)現(xiàn)改了代碼后炕檩,命令行是有顯示在編譯的斗蒋。
嗯捌斧。。泉沾。說明熱更新是沒問題捞蚂,可能是更新,但是更新到瀏覽器這一步不行了跷究,或者說 webpack-dev-server 沒有真正地通知到瀏覽器姓迅,所以沒有刷新。
然后又搜了一波“Vue 瀏覽器無法正常刷新”俊马,這里省略1小時的糾結(jié)丁存。。柴我。
sockjs-node
后面無聊點開了 Network 看到下面的報錯:
好奇點開這個請求詳情:
這里我關注了到了 Request URL: http://172.20.10.2:8080/sockjs-node/info?t=1590456177387解寝。這里有 "sockjs" 字眼,嗯艘儒,sock聋伦?socket !=缯觥觉增!!(此時應該有BGM)
我可以合理地提出自己的一個猜想:webpack-dev-server 和瀏覽器應該是一個雙工的過程。因為第一次連接沒有連接上翻斟,瀏覽器就根本沒有在監(jiān)聽 webpack-dev-server逾礁,所以代碼改了,瀏覽器并沒不知道访惜!
為了驗證我的猜想敞斋,我查了下這個請求,發(fā)現(xiàn)了 sockjs-node 這個庫疾牲,https://github.com/sockjs/sockjs-node植捎,果然是一個 websocket 的東西。同時阳柔,我還查了很多中文的垃圾博客焰枢,為什么要說垃圾,因為抄襲舌剂。
回到問題本身济锄,根據(jù)上面的這些博客,可以知道 sockjs-node 是一個:
首先霍转,sockjs-node是何方神圣荐绝?不難查出,sockjs-node是一個JavaScript庫避消,提供跨瀏覽器JavaScript的API低滩,創(chuàng)建了一個低延遲召夹、全雙工的瀏覽器和web服務器之間通信通道。 —— 來自各種抄襲博客
那問題就變簡單了恕沫,只要搞清楚為什么不能響應這個請求就好了监憎。
都是 VPN 的鍋
因為在查資料和嘗試各路方法的時候,我總會不斷重啟我的 Vue 項目婶溯。然后有一次鲸阔,瀏覽器竟然可以自動刷新了。此時的我還清楚地記得我在重啟前把 VPN 關了迄委,因為之前要裝個 npm 包褐筛。
然后我嘗試了幾次,只要開 VPN 就炸叙身,關了 VPN 就成功了死讹。所以這次我搜索的內(nèi)容變成了 “Vue 熱更新 VPN”,搜了幾次發(fā)現(xiàn)了這篇文章:https://blog.csdn.net/gulang03/article/details/89217273
里面遇到的就是我的問題曲梗,這里總結(jié)一下,因為這個 Request 的地址是局域網(wǎng)的地址妓忍,而我用了 VPN 代理虏两,它就會當成是 public address 去請求。一個是局域的世剖,一個 public address 定罢,那肯定是無法響應的嘛。
OK旁瘫,到此為止祖凫,其實已經(jīng)有兩種解決方法了:
- 把當前 IP 加到 VPN 的 exclude list
- 每次項目重啟的時候,把 VPN 關了酬凳。之后是可以再次打開的惠况,因為只要第一次 websocket 連接成功后,后面就可以正常通信了宁仔。不過稠屠,刷新就不行了,因為每次刷新又得創(chuàng)建連接翎苫。
修改 host
仔細想想权埠,問題不就是因為他用了 public address 所以無法建立連接么?那為什么不直接把 http://172.20.10.2:8080/sockjs-node/info?t=1590456177387
改成 http://localhost:8080/sockjs-node/info?t=1590456177387煎谍。別用 172.20.10.2攘蔽,用 localhost 唄,這肯定是能訪問到本機的呀呐粘。
所以我又開始搜索 “Vue How to change sockjs-node host”满俗,搜出了兩遍比較好的 Github Issue转捕。
第一篇 https://github.com/gtalarico/django-vue-template/issues/5 和我的問題有的類似,也是上面這個請求無法訪問了漫雷。不過他好像是 Django 的問題瓜富。但是上面給的方法是可以解決的。
在 package.json 改成 "server": "vue-cli-service serve --host 127.0.0.1 --port 8080"
降盹。這樣 host 就是 127.0.0.0 訪問的就是本機了与柑。
另一篇 https://github.com/vuejs/vue-cli/issues/1525 說的就是 Vue 這個 cli 的 websocket 就是連不上,怎么修改 Host 的蓄坏。這里的解決方法也差不多价捧。
在 vue.config.js 里添加 devServer 的配置:
module.exports = {
...
devServer: {
host: '0.0.0.0',
public: '0.0.0.0:8080',
disableHostCheck: true
}
}
這樣訪問的還是本機,websocket 也是可以成功建立的涡戳。
但是结蟋,這里也有不好的地方,它改了 Network渔彰。你可能會問嵌屎,改了 Network 怎么了?先看看原來是怎么樣的:
一個是本地的地址恍涂,一個是公開的地址宝惰,有了公開的地址就可以在手機里調(diào)試呀。不然每次都要 ifconfig
去找本機的 IP再沧,好麻煩尼夺。而且別人看到你提交的代碼可能會過來找你。
總強
總結(jié)一下炒瘸,問題其實就是因為開了代理淤堵,代理以為你的局域網(wǎng)地址是 public address,所以并不能得到響應顷扩。因此 webpack-dev-server 和瀏覽器的雙工通信沒有成功連接拐邪,瀏覽器就無法監(jiān)聽到 webpack-dev-server 的熱更新。最后瀏覽器就變成了憨憨隘截。
解決方法有下面幾種:
- 每次開 Vue 項目時候庙睡,先關了 VPN。等項目啟動了再開 VPN技俐,因為雙工通信只要第一次連接好了乘陪,后面就能正常通信了,VPN 再也不會搗亂雕擂。缺點是不能刷新啡邑,一刷新又會發(fā) Request了。
- 把當前 IP 地址加到 VPN 的 exclude list井赌。這樣就還是會訪問局域地址谤逼,不會以為它是 public addresss贵扰。
- 修改請求的 Host:
3.1 可以在 package.json 里改成"server": "vue-cli-service serve --host 127.0.0.1 --port 8080"
。
3.2 或者在 vue.config.js 里添加
module.exports = {
...
devServer: {
host: '0.0.0.0',
public: '0.0.0.0:8080',
disableHostCheck: true
}
}