摘要:歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面不僅僅是代碼這一節(jié),請(qǐng)跟隨筆者聊一聊,網(wǎng)頁(yè)的分段傳輸與渲染,用一些非常規(guī)手段優(yōu)化我們的網(wǎng)站響應(yīng)速度??梢蕴幚硗暌粔K就返回一塊,讓瀏覽器盡早的接收到,可以先行渲染。
歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面(不僅僅是代碼):
https://segmentfault.com/blog...
這一節(jié),請(qǐng)跟隨筆者聊一聊,網(wǎng)頁(yè)的分段傳輸與渲染,用一些非常規(guī)手段優(yōu)化我們的網(wǎng)站響應(yīng)速度。
1 CHUNKED編碼 1.1 傳統(tǒng)的渲染方法 1.1.1 傳統(tǒng)的渲染方法怎么做?按照常理,我們渲染一張網(wǎng)頁(yè),必定是網(wǎng)頁(yè)全部拼裝完畢,然后生成HTML字符串,傳送至客戶端。這也意味著,如果一張網(wǎng)頁(yè)處理的有快有慢的話,必須串行等到所有的邏輯都處理完畢。后端才能進(jìn)行返回。(這也是我們目前網(wǎng)頁(yè)的一般邏輯)。如下面的例子,三個(gè)很慢的讀數(shù)據(jù)操作,均執(zhí)行完畢后,才傳送渲染頁(yè)面。渲染效果如圖1.1.1,15s之后才傳送并渲染出頁(yè)面:
normal.php
的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出>的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出>的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出>的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)"; } $var1 = getOneData(); function getTwoData() { usleep(5000000); return "是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)"; } $var2 = getTwoData(); function getThreeData() { usleep(5000000); return "我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出>的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出>的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出>的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出>的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)"; } $var3 = getThreeData(); // 渲染模板并輸出 include("./normal.html.php");
normal.html.php
1.2.3.
圖1.1.1
上述例子,在本文后github中的normal文件夾中。
1.1.2 傳統(tǒng)的渲染方法有哪些弊端?如上所示,我們能看到,直出的網(wǎng)頁(yè)中,存在著后端數(shù)據(jù)串行,互相等待的尷尬局面。這也為我們后續(xù)的優(yōu)化埋下了伏筆。
1.2 分段傳輸 1.2.1 何為分段傳輸?http1.1中引入了一個(gè)http首部,Transfer-Encoding:chunked。這個(gè)首部標(biāo)識(shí)了實(shí)體采用chunked編碼傳輸,chunked編碼可以將實(shí)體分塊兒進(jìn)行傳輸,并且chunked編碼的每一塊內(nèi)容都會(huì)自標(biāo)識(shí)長(zhǎng)度。這給了web開發(fā)者一個(gè)啟示,如果需要多個(gè)數(shù)據(jù),而多個(gè)數(shù)據(jù)均返回較慢的話??梢蕴幚硗暌粔K就返回一塊,讓瀏覽器盡早的接收到html,可以先行渲染。
1.2.2 如何分段傳輸?既然知道了我們可以將網(wǎng)頁(yè)一塊兒一塊兒的傳送,那么我們就可以將上面的網(wǎng)頁(yè)進(jìn)行改造,拿好一塊兒需要的數(shù)據(jù),便渲染一塊兒,無(wú)需等待,而模板方面,自然也要拆分為三段,供服務(wù)端拿一塊兒的模板,就渲染一塊兒出去,效果如圖1.2.2.1。
normal.php
的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出>的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出>的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出>的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)我是取出的第一個(gè)數(shù)據(jù)"; } // 取出第一塊兒的數(shù)據(jù) $var1 = getOneData(); // 渲染第一塊兒 include("./normal1.html.php"); //刷新到緩沖區(qū),渲染第一份兒模板,傳送到客戶端 ob_flush(); flush(); function getTwoData() { usleep(5000000); return "我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出>的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出>的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出>的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出>的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)我是取出的第二個(gè)數(shù)據(jù)"; } // 取出第二塊兒的數(shù)據(jù) $var2 = getTwoData(); // 渲染第二塊兒 include("./normal2.html.php"); //刷新到緩沖區(qū),渲染第二份兒模板,傳送到客戶端 ob_flush(); flush(); function getThreeData() { usleep(5000000); return "我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出>的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出>的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出>的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出>的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)我是取出的第三個(gè)數(shù)據(jù)"; } // 獲取第三塊兒的數(shù)據(jù) $var3 = getThreeData(); // 渲染第三塊兒 include("./normal3.html.php"); // 將第三份兒的模板,傳送到客戶端 ob_flush(); flush();
normal1.html.php
1.
normal2.html.php
2.
normal3.html.php
3.
圖1.2.2.1
上述例子,在本文后github中的chunked文件夾中。
對(duì)比圖圖1.1.1與圖1.2.2.1我們可以發(fā)現(xiàn),雖然最后總的處理時(shí)長(zhǎng)不變,但是采用了分段輸出的網(wǎng)頁(yè),可以盡早的將一段HTML渲染到客戶端,這樣用戶可以使用先到達(dá)的部分。另一方面,盡早的頁(yè)面反饋,也可以減少用戶等待的焦躁情緒。綜上,使用此種優(yōu)化方法,可以提速網(wǎng)頁(yè)的渲染速度。
1.2.3 分段傳輸小TIPs我們代碼雖然如上所述,但是讀者嘗試的時(shí)候可能會(huì)發(fā)現(xiàn),并沒有什么效果。和我截圖并不一樣,還是等到15s后一起渲染出來(lái)了。這里要提醒大家一下,可能是由于nginx配置的原因。如果使用的是nginx做server的話,要使用如下配置才能看到效果。
http { .... fastcgi_buffer_size 1k; fastcgi_buffers 16 1k; gzip off; .... }
其實(shí)讀者們可以這么理解上面的配置,nginx會(huì)在攢夠一塊兒緩沖區(qū)的量后,可以將一塊兒數(shù)據(jù)發(fā)出去。上面我們配置了fastcgi_buffers 16 1k; 就是16塊兒,大小為1K的緩存。
我們的數(shù)據(jù)量太小了,連默認(rèn)的一塊兒緩沖區(qū)都填不滿,沒法看到分塊兒發(fā)送的效果,所以這里我們將緩沖區(qū)給調(diào)小為1K,這樣就能1K為單位分塊兒,1K一發(fā),體現(xiàn)出實(shí)驗(yàn)效果了。筆者這里建議做實(shí)驗(yàn)的時(shí)候,最好把gzip給關(guān)了,因?yàn)?,咱們做?shí)驗(yàn)的時(shí)候數(shù)據(jù)量不大,實(shí)際使用中建議chunked與gzip均開啟(如圖1.2.3.1,如果量比較大的話,gzip與chunked均開啟使用效果更佳哦~~~)。
圖1.2.3.1
當(dāng)頁(yè)面的某些后端處理比較耗時(shí)的時(shí)候,可以試試采用分段傳輸,可以渲染一部分,就發(fā)送一部分到客戶端,雖然總時(shí)長(zhǎng)不變,但是瀏覽器在全部傳輸完之前不會(huì)處于干等狀態(tài)。可以盡早的渲染并給予用戶反饋。
2 BIGPIPE 2.1 分段傳輸?shù)木窒?/b>剛剛筆者和讀者們一起做了分段傳輸?shù)膶?shí)驗(yàn),思路是基于讀者們想展示的網(wǎng)頁(yè)也是上快下慢的??墒亲x者們有沒有想過(guò),如果整個(gè)網(wǎng)頁(yè)中,最快的是下方,而最慢的是上方呢?這樣我們就無(wú)法利用分段傳輸?shù)膬?yōu)勢(shì)了嗎?如圖2.1.1,整個(gè)頁(yè)面依舊是被最慢的第一部分?jǐn)?shù)據(jù)渲染給hold住了。而后兩塊兒渲染較快,完全可以先傳輸過(guò)來(lái)。
圖2.1.1上述例子,在本文后github中的bigpipprepare文件夾中。
2.2 解決分段傳輸順序的問(wèn)題看完上述描述,讀者們肯定在想,如果能把最慢的部分放置于底部傳過(guò)來(lái)就好了。于是有了一種加載思路,便是使用js回填的方式,先將左邊最慢的部分架空,然后在底部寫上js回填。這樣不就可以先渲染相對(duì)較快的右側(cè)兩塊兒了么。如圖2.2.1
后端可以先渲染快的模板,然后再渲染最慢的模板。normal1.html.php
normal2.html.php
2.normal3.html.php
3.normal4.html.php
圖2.2.1
如上圖,可以看到49ms的時(shí)候,就已經(jīng)渲染出來(lái)了右側(cè)兩塊兒,2S的時(shí)候,左側(cè)也渲染出來(lái)了。上述例子,在本文后github中的bigpipe文件夾中。
2.3 回填思路的擴(kuò)展與并行化我們剛剛做了一個(gè)實(shí)驗(yàn),是將耗時(shí)最慢的塊兒放在底部。然而,事實(shí)情況是,如果你也不知道哪塊兒慢了呢?或者是,你的幾塊兒數(shù)據(jù)區(qū)塊兒是并行的呢?出于剛剛的經(jīng)驗(yàn),我們可以把頁(yè)面上所有的塊兒都架空,然后并行渲染,誰(shuí)快誰(shuí)就先渲染回填js。這樣就可以達(dá)到并行且先到先渲染的目的了。我這里做了個(gè)php并行取并回填的實(shí)驗(yàn),如圖2.3.1,可以看到,中間紅色的雖然被阻塞,但是框架先行渲染出來(lái)了所有的內(nèi)容均是空的。綠色最快,先行回填渲染了出來(lái),藍(lán)色稍慢,也跟著渲染了出來(lái),最后紅色完畢,回填渲染結(jié)束了。
并行渲染的PHP(normal.php)主框架的模板,架空,等待回填。normal_frame.html.php
具體回填模板,normal1.html.php/normal2.html.php/normal3.html.php
圖2.3.1上述例子,在本文后github中的bigpipeparal文件夾中。
2.4 為什么不用ajax?相信讀著在此處會(huì)有疑問(wèn),為什么慢的數(shù)據(jù),不用ajax去請(qǐng)求呢?這樣模板框架也能盡早的渲染出來(lái)。ajax畢竟是請(qǐng)求。相信很多讀著也有這樣的經(jīng)歷,后端處理如果遇到了瓶頸,那么有的時(shí)候我們會(huì)選擇同步頁(yè)面渲染完之后,再發(fā)個(gè)請(qǐng)求去獲取后端數(shù)據(jù)。但是筆者認(rèn)為,這樣做有一定弊端:
3 分段傳輸與bigpipe適用場(chǎng)景 3.1 分段傳輸?shù)倪m用場(chǎng)景
1、ajax畢竟是個(gè)請(qǐng)求,請(qǐng)求就要有連接,要有解析等過(guò)程。
2、服務(wù)端和客戶端都會(huì)有閑的時(shí)候,發(fā)送ajax之前服務(wù)端閑,發(fā)送ajax出去之后,瀏覽器又閑著了。
所以,我們使用bigpipe的方式還是比多發(fā)送一個(gè)ajax有優(yōu)勢(shì)的。筆者總結(jié)了一些使用分塊兒傳輸比較合適的場(chǎng)景
3.2 使用bigpipe的場(chǎng)景
1 前端需要盡早傳輸head中的一些css/js外聯(lián)文件的情況下(可以先f(wàn)lush給客戶端head前面的html內(nèi)容,讓瀏覽器盡早的去請(qǐng)求)
2 后端處理渲染的數(shù)據(jù),上方較快,下方較慢的情況(可以先行渲染上方較快的部分)對(duì)于更為復(fù)雜一點(diǎn)的bigpipe方式,如果上面的情況就適用于你的網(wǎng)站了的話,則最好采用簡(jiǎn)單的分塊傳輸,否則如下情況,需要回填,則采用bigpipe方式渲染頁(yè)面。畢竟,使用js回填還是有性能損耗的。
3.3 國(guó)內(nèi)的應(yīng)用
1 后端有較慢的數(shù)據(jù)處理,阻塞住了頁(yè)面的情況下,且最慢的部分不是在網(wǎng)頁(yè)的最后。(可以把最慢的部分變?yōu)榛靥?
2 后端有多塊兒數(shù)據(jù)要并行處理的情況下(你也不知道哪塊兒先回來(lái)了,所以先渲染一個(gè)架子。對(duì)于并行的請(qǐng)求,先回來(lái)的先f(wàn)lush回填)據(jù)筆者觀察,新浪微博正是采用了bigpipe的方式進(jìn)行渲染,如圖3.3.1,我們看到新浪微博的左側(cè)導(dǎo)航欄與中間feed流區(qū)塊兒都是架空的:
圖3.3.1
在下方,有對(duì)左側(cè)導(dǎo)航欄和中間feed流部分的回填,如圖3.3.2
圖3.3.2所以,整個(gè)網(wǎng)頁(yè)的渲染效果如下(如圖3.3.3/圖3.3.4/圖3.3.5)
4 課后作業(yè)
圖3.3.3
圖3.3.4
圖3.3.5
筆者猜測(cè),可能微博是并行渲染這幾塊兒的數(shù)據(jù),所以采用了bigpipe的方式。請(qǐng)讀者們回想一下,自己的網(wǎng)站到底適不適合使用分塊兒傳輸,能否使用上面的技術(shù),使自己的網(wǎng)站更快一些呢?如果使用的話,是適合使用普通的chuned提速呢?還是使用bigpipe進(jìn)行提速呢?
如有說(shuō)明不周的地方歡迎回復(fù)詳詢
本文中所有的例子,均在我的github上可以找到:
https://github.com/houyu01/ch...接下來(lái)的一篇文章,我將會(huì)和讀者們一起聊聊HTTPS那些事兒,不要走開,請(qǐng)關(guān)注我.....
https://segmentfault.com/a/11...
如果喜歡本文請(qǐng)點(diǎn)擊下方的推薦哦,你的推薦會(huì)變?yōu)槲依^續(xù)更文的動(dòng)力。
以上內(nèi)容僅代表筆者個(gè)人觀點(diǎn),如有意見筆者愿意學(xué)習(xí)參考各讀者的建議。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/87785.html
摘要:歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面不僅僅是代碼作為現(xiàn)代應(yīng)用,的大量使用,使得前端工程師們?nèi)粘5拈_發(fā)少不了拼裝模板,渲染模板。我們今天就來(lái)聊聊,拼裝與渲染模板的那些事兒。一改俱改,一板兩用。 歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面(不僅僅是代碼):https://segmentfault.com/blog...
摘要:歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面不僅僅是代碼作為現(xiàn)代應(yīng)用,的大量使用,使得前端工程師們?nèi)粘5拈_發(fā)少不了拼裝模板,渲染模板。我們今天就來(lái)聊聊,拼裝與渲染模板的那些事兒。一改俱改,一板兩用。 歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面(不僅僅是代碼):https://segmentfault.com/blog...
摘要:歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面不僅僅是代碼作為現(xiàn)代應(yīng)用,的大量使用,使得前端工程師們?nèi)粘5拈_發(fā)少不了拼裝模板,渲染模板。我們今天就來(lái)聊聊,拼裝與渲染模板的那些事兒。一改俱改,一板兩用。 歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面(不僅僅是代碼):https://segmentfault.com/blog...
摘要:歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面不僅僅是代碼從說(shuō)起要想了解,得從一個(gè)新的規(guī)則說(shuō)起。因?yàn)橛脩魶]有安裝的話,我們強(qiáng)制要求顯示也沒有辦法。國(guó)內(nèi)有阿里巴巴的平臺(tái),可以選自己喜歡的圖標(biāo)導(dǎo)出。 歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面(不僅僅是代碼):https://segmentfault.com/blog/fr...
摘要:歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面不僅僅是代碼從說(shuō)起要想了解,得從一個(gè)新的規(guī)則說(shuō)起。因?yàn)橛脩魶]有安裝的話,我們強(qiáng)制要求顯示也沒有辦法。國(guó)內(nèi)有阿里巴巴的平臺(tái),可以選自己喜歡的圖標(biāo)導(dǎo)出。 歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面(不僅僅是代碼):https://segmentfault.com/blog/fr...
閱讀 2077·2021-09-22 15:43
閱讀 8759·2021-09-22 15:07
閱讀 1092·2021-09-03 10:28
閱讀 2067·2021-08-19 10:57
閱讀 1080·2020-01-08 12:18
閱讀 2985·2019-08-29 15:09
閱讀 1537·2019-08-29 14:05
閱讀 1649·2019-08-29 13:57