国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

現(xiàn)代腳本的加載

ranwu / 1143人閱讀

摘要:鑒于目前通行的做法就是在所有瀏覽器中一致同仁地加載,相比而言條件可以讓大部分現(xiàn)代瀏覽器用戶避免加載代碼。

原文地址: Modern Script Loading, 文章作者是Preact作者Jason Miller

背景知識(shí)

先簡(jiǎn)單介紹一下模塊script(Module script), 它指的是現(xiàn)代瀏覽器支持通過(guò)來(lái)加載現(xiàn)代的ES6模塊. 現(xiàn)代瀏覽器對(duì)ES6現(xiàn)代語(yǔ)法有良好的支持,這意味著我們可以給這些現(xiàn)代瀏覽器提供更緊湊的‘現(xiàn)代代碼’,一方面可以減小打包的體積,減少網(wǎng)絡(luò)傳輸?shù)膸挘硗膺€可以提高腳本解析的效率和運(yùn)行效率.

下圖來(lái)源于module/nomodule pattern, 對(duì)比了模塊script傳統(tǒng)(legacy) script的性能:

體積對(duì)比:

Version Size (minified) Size (minified + gzipped)
ES2015+ (main.mjs) 80K 21K
ES5 (main.es5.js) 175K 43K

解析效率:

Version Parse/eval time (individual runs) Parse/eval time (avg)
ES2015+ (main.mjs) 184ms, 164ms, 166ms 172ms
ES5 (main.es5.js) 389ms, 351ms, 360ms 367ms

Ok,為了兼容舊瀏覽器, module/nomodule pattern這篇文章介紹了一種module/nomodule 模式, 簡(jiǎn)單說(shuō)就是同時(shí)提供兩個(gè)script, 由瀏覽器來(lái)決定加載哪個(gè)文件






看起來(lái)很美好是吧? 現(xiàn)實(shí)是:中間存在一些瀏覽器,它們可以識(shí)別模塊script但是不認(rèn)識(shí)nomodule屬性, 這就導(dǎo)致了這些瀏覽器會(huì)同時(shí)加載這兩個(gè)文件(下文統(tǒng)一稱為‘雙重加載’(over-fetching)).

OK,正式進(jìn)入正文. 給正確的瀏覽器交付正確代碼是一件棘手的事情。本文會(huì)介紹幾種方式, 來(lái)解決上述的問(wèn)題:

給現(xiàn)代瀏覽器伺服"現(xiàn)代的代碼"對(duì)性能有很大的幫助。所以你應(yīng)該針對(duì)現(xiàn)代瀏覽器提供包含更緊湊和優(yōu)化的現(xiàn)代語(yǔ)法的Javascript包,同時(shí)又可以保持對(duì)舊瀏覽器的支持

現(xiàn)有的工具鏈的生態(tài)系統(tǒng)基本都是在module/nomodule模式上整合的,它聲明式加載現(xiàn)代和傳統(tǒng)代碼(legacy code),即給瀏覽器提供兩個(gè)源代碼,讓它來(lái)自己來(lái)決定用哪個(gè):

  
  

然而現(xiàn)實(shí)總是給你當(dāng)頭一棒,它沒(méi)我們期望的那么簡(jiǎn)單直接。上述基于HTML的加載方式在Edge和Safari中會(huì)被同時(shí)加載!

怎么辦?

怎么辦?我們想依賴瀏覽器來(lái)交付不同的編譯目標(biāo),但是一些舊瀏覽器并不能優(yōu)雅地支持這種簡(jiǎn)潔的寫法。

首先,Safari 在10.1開始支持JS模塊, 但不支持nomodule屬性。值得慶幸的是,Sam找到了一種方法,可以通過(guò)Safari 10和11中非標(biāo)準(zhǔn)的beforeload事件來(lái)模擬 nomodule, 也就是可以認(rèn)為Safari 10.1開始是可以支持module/nomodule模式

選項(xiàng)1: 動(dòng)態(tài)加載

我們可以實(shí)現(xiàn)一個(gè)小型script加載器來(lái)規(guī)避這個(gè)問(wèn)題,工作原理類似于LoadCSS。只不過(guò)這里需要依靠瀏覽器的來(lái)實(shí)現(xiàn)ES模塊和nomodule屬性.

我們首先嘗試執(zhí)行一個(gè)模塊script進(jìn)行"石蕊試驗(yàn)"(litmus test), 然后由這個(gè)試驗(yàn)的結(jié)果來(lái)決定加載現(xiàn)代代碼還是傳統(tǒng)代碼:

  


  
  

然而,這個(gè)解決方案必須等待進(jìn)行‘石蕊試驗(yàn)’模塊script執(zhí)行完成, 才能開始注入script。這是因?yàn)?b>

看起來(lái)已經(jīng)很完美了,還有什么問(wèn)題呢?我們還沒(méi)考慮預(yù)加載(preloading)

這個(gè)有點(diǎn)蛋疼, 因?yàn)橐话銥g覽器只會(huì)靜態(tài)地掃描HTML,然后查找它可以預(yù)加載的資源。 我們上面介紹的模塊加載器是完全動(dòng)態(tài)的,所以瀏覽器在沒(méi)有運(yùn)行我們的代碼之前,是沒(méi)辦法發(fā)現(xiàn)我們要預(yù)加載現(xiàn)代還是傳統(tǒng)的Javascript資源的。

不過(guò)有一個(gè)解決辦法,就是不完美:就是使用來(lái)預(yù)加載現(xiàn)代版本的包, 舊瀏覽器會(huì)忽略這條規(guī)則,然而目前只有Chrome支持這么做:

  
  
  

其實(shí)預(yù)加載這種技術(shù)是否有效,取決于嵌入你的腳本的HTML文檔的大小

如果你的HTML載荷很小, 比如只是一個(gè)啟動(dòng)屏或者只是簡(jiǎn)單啟動(dòng)客戶端應(yīng)用,那么放棄預(yù)加載掃描對(duì)你的應(yīng)用性能影響很小。
如果你的應(yīng)用使用服務(wù)器渲染大量有意義的HTML, 并以流(stream)的方式傳輸給瀏覽器,那么預(yù)加載掃描就是你的朋友,但這也未必是最佳方法。

譯注: 現(xiàn)代瀏覽器都支持分塊編碼傳輸,等服務(wù)端完全輸出html可能有一段空閑時(shí)間,這時(shí)候可以通過(guò)預(yù)加載技術(shù),讓瀏覽器預(yù)先去請(qǐng)求資源

大概代碼如下:

  
  
  

還要指出的是,支持JS模塊的瀏覽器一般也支持。對(duì)于某些網(wǎng)站,相比依靠modulepreload, 使用可能更有意義。不過(guò)性能上面可能欠點(diǎn),因?yàn)閭鹘y(tǒng)的腳本預(yù)加載不會(huì)像modulepreload一樣隨著時(shí)間的推移而去展開解析工作(rel=preload只是下載,不會(huì)嘗試去解析腳本)。

選項(xiàng)2: 用戶代理嗅探

我辦法拿出一個(gè)簡(jiǎn)潔的代碼示例,因?yàn)橛脩舸頇z測(cè)不在本文的范圍之內(nèi),推薦閱讀這篇Smashing Magazine文章

本質(zhì)上,這種技術(shù)在每個(gè)瀏覽器上都使用 `; } else { html += ` `; } response.end(html); }

對(duì)于那些已經(jīng)在使用服務(wù)端渲染的網(wǎng)站來(lái)說(shuō),用戶代理嗅探是一個(gè)比較有效的解決方案

選項(xiàng) 3:不考慮舊版本瀏覽器

注意這里的‘舊版本瀏覽器’特指那些出現(xiàn)雙重加載的瀏覽器. 對(duì)于module/nomodule模式支持比較差(即雙重加載)的主要是一些舊版本的Chrome、Firefox和Safari. 幸運(yùn)的是這部分瀏覽器的市場(chǎng)范圍通常是比較窄,因?yàn)橛脩魰?huì)自動(dòng)升級(jí)到最新的版本。Edge 16-18是例外, 但還有希望: 新版本的Edge會(huì)使用基于Chromium的渲染器,可以不受該問(wèn)題的影響.

對(duì)于某些應(yīng)用程序來(lái)說(shuō),接受這一點(diǎn)妥協(xié)是完全合理的:你可以給90%的瀏覽器中提供現(xiàn)代代碼,讓他們獲得更好的體驗(yàn),而極少數(shù)舊瀏覽器不得不拋棄它們,它們只是付出的額外帶寬(即雙重加載),并不影響功能。值得注意的是,占據(jù)移動(dòng)端主要市場(chǎng)份額的用戶代理不會(huì)有雙重加載問(wèn)題,所以這些流量不太可能來(lái)自于低速或者高昂流量費(fèi)的手機(jī)。

如果你的網(wǎng)站用戶主要使用移動(dòng)設(shè)備或較新版本的瀏覽器,那么最簡(jiǎn)單的module/nomodule模式將適用于你的絕大多數(shù)用戶, 其他用戶就不考慮了,反正也是可以跑起來(lái)的, 優(yōu)先考慮大多數(shù)用戶的體驗(yàn)。

  


  


  
  
  
選項(xiàng) 4: 使用條件包

nomodule可以巧妙地用來(lái)條件加載那些現(xiàn)代瀏覽器不需要的代碼, 例如polyfills。通過(guò)這種方法,最壞的情況就是polyfill和bundle都會(huì)被加載(例如Safari 10.1),但這畢竟是少數(shù)。鑒于目前通行的做法就是在所有瀏覽器中一致同仁地加載polyfills,相比而言, 條件polyfills可以讓大部分現(xiàn)代瀏覽器用戶避免加載polyfill代碼。

  


  
  

Angular CLI支持配置這種方式來(lái)加載polyfill, 查看Minko Gechev的代碼示例.
了解了這種方式之后,我決定在preact-cli中支持自動(dòng)polyfill注入,你可以查看這個(gè)PR

如果你使用Webpack,這里有一個(gè)html-webpack-plugin插件可以方便地為polyfill包添加nomodule屬性.

你應(yīng)該怎么做?

答案取決于你的使用場(chǎng)景, 選擇和你們的架構(gòu)匹配的選項(xiàng):
如果你的應(yīng)用只是客戶端渲染, 而且你的HTML不超過(guò)一個(gè)

閱讀需要支付1元查看
<