摘要:很多同學(xué)肯定都想過(guò)服務(wù)端渲染的問(wèn)題。然而一看關(guān)于服務(wù)端渲染的文檔,可能就被唬住了。啪啪啪,啪啪啪好,然后就好了,不到行的代碼,我們就實(shí)現(xiàn)了一個(gè)通用化的服務(wù)化的單頁(yè)應(yīng)用服務(wù)端渲染解決方案。
前端發(fā)展到現(xiàn)在,SPA應(yīng)該已經(jīng)被應(yīng)用的非常廣了。可惜的是,我們前進(jìn)的是快,而人家搜索引擎爬蟲(chóng)跟用戶(hù)的瀏覽器設(shè)備還跟不上腳步。辛辛苦苦寫(xiě)好的單頁(yè)應(yīng)用,結(jié)果到了SEO跟瀏覽器兼容這一步懵逼了。
很多同學(xué)肯定都想過(guò)服務(wù)端渲染的問(wèn)題。然而一看vue、react關(guān)于服務(wù)端渲染的文檔,可能就被唬住了。之前寫(xiě)好的并不能無(wú)縫遷移。而且,每當(dāng)有個(gè)項(xiàng)目,就需要去run一套node服務(wù)。當(dāng)然,架構(gòu)能力好些的朋友,可以做好集中化管理。
所以,當(dāng)我想在項(xiàng)目中,采用vue或者react的時(shí)候,就遇到這些非常大的阻力。正當(dāng)我頭疼腦熱的時(shí)候呢,我發(fā)現(xiàn)了一條新途徑。
在前不久呢,同事在群里分享了puppeteer,它GitHub的介紹如下:
Puppeteer is a Node library which provides a high-level API to control headless Chrome over the DevTools Protocol. It can also be configured to use full (non-headless) Chrome.
大意就是說(shuō),一個(gè)提供操作Headless Chrome的API的node庫(kù)。
再具體的說(shuō),就是能在node環(huán)境中,通過(guò)一些API,來(lái)“模擬”真實(shí)chrome訪問(wèn)頁(yè)面,并對(duì)其進(jìn)行模擬用戶(hù)操作、獲取DOM等。
那既然它能夠像真實(shí)Chrome那樣去訪問(wèn)頁(yè)面并且輸出渲染后的html,我為什么不能通過(guò)它來(lái)給我們做服務(wù)端渲染呢?
設(shè)想一下,我們有這樣一個(gè)服務(wù)A,它能夠像chrome一樣訪問(wèn)指定頁(yè)面,并把最終頁(yè)面上的dom返回給你。
而你原本的業(yè)務(wù)服務(wù)器B,只需要判斷是爬蟲(chóng),或者低版本IE來(lái)訪問(wèn)時(shí),調(diào)取該服務(wù),得到html,將html返回給用戶(hù),這就實(shí)現(xiàn)了服務(wù)端渲染。大致流程圖如下:
有這樣一個(gè)思路后,我們就想辦法來(lái)實(shí)踐它。實(shí)踐的過(guò)程,就是解決問(wèn)題的過(guò)程。仔細(xì)想想,我們會(huì)遇到如下幾個(gè)問(wèn)題:
Q1: 即使是模擬Chrome去請(qǐng)求頁(yè)面,很多時(shí)候視圖也是異步渲染的。比如先請(qǐng)求列表接口,得到數(shù)據(jù)再渲染出列表DOM。這個(gè)時(shí)間,我們并沒(méi)有辦法把控。那這個(gè)服務(wù),到底時(shí)候才應(yīng)該把加載完成的HTML返回呢?
遇到問(wèn)題時(shí),首先可以看看人家的文檔 Puppeteer API。欣喜的是,我們找到了如下幾個(gè)方法:
page.waitFor(selectorOrFunctionOrTimeout[, options[, ...args]]) page.waitForFunction(pageFunction[, options[, ...args]]) page.waitForNavigation(options) page.waitForSelector(selector[, options])
我們可以通過(guò)一些設(shè)定,讓頁(yè)面在某種情況下才返回。比如我們通過(guò)設(shè)定 page.waitForSelector("#app"), 讓頁(yè)面出現(xiàn) id="app" 的元素時(shí),才把html內(nèi)容返回。
或者通過(guò)設(shè)定 page.waitForFunction("window.innerWidth < 100"),當(dāng)頁(yè)面寬度小于100px時(shí),才將此時(shí)的html內(nèi)容返回。
通過(guò)這些方法,我們就能有辦法控制,想要輸給爬蟲(chóng)的,是什么時(shí)候、什么樣的頁(yè)面。
Q2: 如果IE用戶(hù)訪問(wèn)量比較大怎么辦。我們雖然通過(guò)這樣的系統(tǒng),讓本渲染不出頁(yè)面的部分瀏覽器(IE9以下)能夠渲染出頁(yè)面了。但這樣的請(qǐng)求過(guò)程相對(duì)而言會(huì)更耗時(shí),這不是很合理。
那我們只要做一個(gè)緩存系統(tǒng)便好。每次請(qǐng)求,都會(huì)去判斷此請(qǐng)求是否存在未過(guò)期的緩存HTML,如果存在,則直接返回緩存HTML,否則再去請(qǐng)求頁(yè)面,保存緩存。
Q3: 雖然頁(yè)面是出來(lái)了,IE用戶(hù)還是沒(méi)辦法做一些JS的交互。
這個(gè)我們沒(méi)辦法在服務(wù)層上去解決了,但我們可以在前端上做更友好的交互提示。如果判斷用戶(hù)是低版本IE,則出現(xiàn)一個(gè)小Tip,提示用戶(hù)下載更好的瀏覽器,獲取更好的體驗(yàn)。
Q4: 單頁(yè)應(yīng)用的路由多是用錨點(diǎn)(哈希模式)來(lái)做的,而哈希參數(shù),服務(wù)端無(wú)法獲取,那就沒(méi)辦法請(qǐng)求正確的頁(yè)面了。
這個(gè)有辦法解決,可以采用HTML History模式的路由,如vue-router,然后路由鏈接最好以生成a標(biāo)簽+href的模式寫(xiě)在頁(yè)面中,而不是onclick后js跳轉(zhuǎn),這樣爬蟲(chóng)能最好的爬取整站頁(yè)面。
當(dāng)問(wèn)題都想到辦法解決后,我們就能開(kāi)始真正coding了。
啪啪啪,啪啪啪 => SSR-SERVICE
好,然后就好了,不到200行的代碼,我們就實(shí)現(xiàn)了一個(gè) 通用化的、服務(wù)化的、單頁(yè)應(yīng)用服務(wù)端渲染解決方案。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/88828.html
showImg(https://segmentfault.com/img/bVbvOmp?w=1612&h=888); 隨著React Vue前端框架的興起,出現(xiàn)了Vue-router,react-router-dom等前端路由管理庫(kù),利用他們構(gòu)建出來(lái)的單頁(yè)面應(yīng)用,也是越來(lái)越接近原生的體驗(yàn),再也不是以前的點(diǎn)擊標(biāo)簽跳轉(zhuǎn)頁(yè)面,刷新整個(gè)頁(yè)面了,那么他們的原理是什么呢? 優(yōu)質(zhì)gitHub開(kāi)源練手項(xiàng)目: ...
showImg(https://segmentfault.com/img/bVbvOmp?w=1612&h=888); 隨著React Vue前端框架的興起,出現(xiàn)了Vue-router,react-router-dom等前端路由管理庫(kù),利用他們構(gòu)建出來(lái)的單頁(yè)面應(yīng)用,也是越來(lái)越接近原生的體驗(yàn),再也不是以前的點(diǎn)擊標(biāo)簽跳轉(zhuǎn)頁(yè)面,刷新整個(gè)頁(yè)面了,那么他們的原理是什么呢? 優(yōu)質(zhì)gitHub開(kāi)源練手項(xiàng)目: ...
showImg(https://segmentfault.com/img/bVbvOmp?w=1612&h=888); 隨著React Vue前端框架的興起,出現(xiàn)了Vue-router,react-router-dom等前端路由管理庫(kù),利用他們構(gòu)建出來(lái)的單頁(yè)面應(yīng)用,也是越來(lái)越接近原生的體驗(yàn),再也不是以前的點(diǎn)擊標(biāo)簽跳轉(zhuǎn)頁(yè)面,刷新整個(gè)頁(yè)面了,那么他們的原理是什么呢? 優(yōu)質(zhì)gitHub開(kāi)源練手項(xiàng)目: ...
摘要:也就是說(shuō),我們需要做一個(gè)非單頁(yè)應(yīng)用的工程化項(xiàng)目。現(xiàn)在這個(gè)項(xiàng)目的靜態(tài)資源是以文件哈希值來(lái)控制的。這個(gè)該怎么解決呢感謝,我們可以通過(guò)如下的配置來(lái)實(shí)現(xiàn)意思就是如果圖片是在中引用的則不加哈希值,在文件中引入的則加上。 最近金拱門(mén)比較火,我們先戳開(kāi)它的官網(wǎng)看看。 看完后,如果你老板要是讓你做這么一個(gè)網(wǎng)站,一定要seo,一定要兼容IE,你會(huì)怎么去做呢? 用vue/react吧,單頁(yè)應(yīng)用滿(mǎn)足不了se...
閱讀 2488·2023-04-26 02:18
閱讀 1274·2021-10-14 09:43
閱讀 3842·2021-09-26 10:00
閱讀 6996·2021-09-22 15:28
閱讀 2551·2019-08-30 15:54
閱讀 2615·2019-08-30 15:52
閱讀 486·2019-08-29 11:30
閱讀 3475·2019-08-29 11:05