新聞中心
作為一名前端,開(kāi)發(fā)web頁(yè)面是我們的本職工作。在完成一個(gè)頁(yè)面開(kāi)發(fā)的過(guò)程中,保存代碼然后手動(dòng)刷新頁(yè)面查看效果,這樣的動(dòng)作需要重復(fù)無(wú)數(shù)次,雖然一次這樣的動(dòng)作可能只要花費(fèi)幾秒鐘的時(shí)間,但是次數(shù)多了也挺浪費(fèi)時(shí)間的。

成都創(chuàng)新互聯(lián)專(zhuān)注于中山網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供中山營(yíng)銷(xiāo)型網(wǎng)站建設(shè),中山網(wǎng)站制作、中山網(wǎng)頁(yè)設(shè)計(jì)、中山網(wǎng)站官網(wǎng)定制、小程序定制開(kāi)發(fā)服務(wù),打造中山網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供中山網(wǎng)站排名全網(wǎng)營(yíng)銷(xiāo)落地服務(wù)。
社區(qū)有一款工具可以幫助前端在每次保存完代碼后自動(dòng)刷新瀏覽器頁(yè)面——livereload。
自動(dòng)刷新工具
目前有很多的工具都內(nèi)置了自動(dòng)刷新功能,以下列舉幾個(gè)常見(jiàn)的。
- 瀏覽器插件liveReload
- webpack的webpack-dev-server模塊
- gulp的gulp-livereload模塊
- grunt的grunt-livereload模塊
- 全局模塊puer
這樣的工具有很多,個(gè)人覺(jué)得最方便的要數(shù)puer,只要全局安裝并在工程根目錄下運(yùn)行即可,效果如下。
圖1
自動(dòng)刷新原理
社區(qū)里大多數(shù)的自動(dòng)刷新工具都是使用livereload實(shí)現(xiàn)的,下面我們就分析一下它的內(nèi)部原理是什么?
場(chǎng)景:當(dāng)在編輯器中修改文件內(nèi)容并保存時(shí),瀏覽器自動(dòng)刷新頁(yè)面;
分析:監(jiān)聽(tīng)文件的修改,并且把修改的動(dòng)作通知瀏覽器。監(jiān)聽(tīng)操作可以用chokidar模塊完成,通知操作可以用websocket來(lái)做。
根據(jù)以上的分析,我們要搭建一個(gè)小服務(wù)器,這個(gè)服務(wù)器可以訪問(wèn)被修改的文件、監(jiān)聽(tīng)文件修改以及與瀏覽器通信。
瀏覽器這邊通過(guò)websocket接收服務(wù)器傳來(lái)的指令來(lái)刷新頁(yè)面內(nèi)容,頁(yè)面刷新的邏輯可以封裝在livereload.js中,這是一個(gè)單獨(dú)的js文件,可以由html文件引入。
整個(gè)流程如下圖。
圖2
自動(dòng)刷新實(shí)現(xiàn)
1、服務(wù)端代碼實(shí)現(xiàn)
1)搭建服務(wù)器
圖3
啟動(dòng)圖3中的服務(wù),通過(guò)localhost:3000可以訪問(wèn)圖左側(cè)html和css兩個(gè)文件,這兩個(gè)文件代表需要開(kāi)發(fā)的代碼。
2)再搭建一個(gè)服務(wù)器,用于頁(yè)面訪問(wèn)livereload.js
圖4
此處用于圖7中html引入livereload.js。
3)搭建websocket服務(wù)器
本文搭建websocket服務(wù)器不再一步步手寫(xiě),而是直接采用ws模塊,如下:
圖5
圖5中封裝了一個(gè)send方法,用于向頁(yè)面發(fā)送刷新通知。
4)監(jiān)聽(tīng)代碼文件的變化
圖6
chokidar模塊監(jiān)聽(tīng)代碼文件的變化,其監(jiān)聽(tīng)的目錄和參數(shù)配置可以自定義。filterRefresh調(diào)用了圖5中定義的send函數(shù),用于發(fā)送指令,指令的數(shù)據(jù)格式也可以自定義,只要頁(yè)面能解析出來(lái)即可。
2、瀏覽器端代碼實(shí)現(xiàn)
1)開(kāi)發(fā)頁(yè)面中引入livereload.js
圖7
這一步在webpack、fis3等構(gòu)建工具中都是自動(dòng)化插入的,無(wú)需手動(dòng)操作。
2)livereload.js中實(shí)現(xiàn)websocket連接
圖8
此處頁(yè)面接收來(lái)自服務(wù)器的指令,然后把它解析出來(lái)執(zhí)行即可。核心指令當(dāng)然是reload,但是不同的資源刷新的方式有所不同,下面會(huì)詳細(xì)介紹。
3)直接刷新頁(yè)面
圖9
4)刷新chrome插件
圖10
5)更新img標(biāo)簽中的圖片
圖11
document.images可以獲取文檔中所有圖片的dom對(duì)象,將每個(gè)圖片地址加一個(gè)版本號(hào)即可刷新。
這里獲取的圖片可能不是本次修改的,那么如何獲取當(dāng)前被修改的文件呢?
如果圖片是自動(dòng)刷新服務(wù)的資源,那么它的src應(yīng)該是localhost:3000/圖片的路徑/圖片名稱。
圖6中websocket傳給頁(yè)面的數(shù)據(jù)中包含了文件在代碼目錄下的路徑,如果被監(jiān)聽(tīng)的目錄下的圖片被修改,那么它的路徑(/home/用戶名/圖片的路徑/圖片名稱)和src會(huì)有一段重合的部分,反之,就不會(huì)有重合的部分。這里就用這個(gè)小技巧來(lái)排除不需要更新的圖片。
6)更新行內(nèi)樣式中的背景圖
圖12
圖13
document.querySelectorAll(`[style*=${selector}]`)可以獲取擁有style屬性的dom,然后通過(guò)dom對(duì)象的style屬性可以獲取style屬性包含的樣式,再通過(guò)具體的css樣式屬性就可以獲取具體的樣式的值,最后通過(guò)正則將背景圖匹配出來(lái)并加上版本號(hào)。
圖14
7)更新內(nèi)嵌和外鏈樣式中的背景圖
圖15
圖16
document.styleSheets可以獲取所有的內(nèi)嵌和外鏈樣式,再通過(guò)cssRules和style屬性可以獲取一組樣式表,剩下的處理就和圖13一致了。
注意:如果遇到了import或者媒體查詢media,需要做遞歸獲取樣式表,這里就不再嗷述了。
8)更新外鏈樣式(不包含import)
圖17
document.getElementsByTagName('link')可以獲取所有的外鏈css,通過(guò)path和href的對(duì)比可以過(guò)濾出本次修改的css文件,然后將外鏈css的href加上版本號(hào)并重新生成一個(gè)link標(biāo)簽插在之前外鏈樣式之后,待新css資源加載完成就可以刪除之前的css資源了。
8)更新外鏈中import中的樣式
圖18
document.querySelectorAll('link')[i].sheet.cssRules[i].href 這樣的寫(xiě)法可以獲取到import進(jìn)來(lái)的css的url。
圖20
總結(jié)
瀏覽器自動(dòng)刷新功能需要服務(wù)端和瀏覽器端配合實(shí)現(xiàn),服務(wù)端的實(shí)現(xiàn)比較簡(jiǎn)單,最大的難點(diǎn)在于瀏覽器端對(duì)css的操作。如果每次只是暴力的刷新整個(gè)頁(yè)面,不考慮對(duì)精準(zhǔn)資源的刷新,可能無(wú)法保持頁(yè)面中已存在的一些狀態(tài)。
現(xiàn)在有條件的公司一般都會(huì)給程序員配備一臺(tái)mac加一個(gè)大屏顯示器,就像下面這樣。
圖21
一個(gè)屏幕打開(kāi)編輯器,另外一個(gè)屏幕打開(kāi)瀏覽器,保存代碼后只要轉(zhuǎn)一下頭就能看見(jiàn)頁(yè)面刷新,不用再在一個(gè)屏幕上切來(lái)切去,開(kāi)發(fā)效率直線上升。
自動(dòng)刷新的原理也是一個(gè)面試題,如果你理解了上面的實(shí)現(xiàn)原理,以后再碰見(jiàn)這道題,肯定so easy!
網(wǎng)站欄目:前端開(kāi)發(fā)還在手動(dòng)刷新頁(yè)面?手把手教你搭建一個(gè)自動(dòng)刷新工具
網(wǎng)站鏈接:http://www.dlmjj.cn/article/coshgig.html


咨詢
建站咨詢
