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

資訊專欄INFORMATION COLUMN

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

ranwu / 1149人閱讀

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

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

背景知識

先簡單介紹一下模塊script(Module script), 它指的是現(xiàn)代瀏覽器支持通過來加載現(xiàn)代的ES6模塊. 現(xiàn)代瀏覽器對ES6現(xiàn)代語法有良好的支持,這意味著我們可以給這些現(xiàn)代瀏覽器提供更緊湊的‘現(xiàn)代代碼’,一方面可以減小打包的體積,減少網絡傳輸的帶寬,另外還可以提高腳本解析的效率和運行效率.

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

體積對比:

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 模式, 簡單說就是同時提供兩個script, 由瀏覽器來決定加載哪個文件






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

OK,正式進入正文. 給正確的瀏覽器交付正確代碼是一件棘手的事情。本文會介紹幾種方式, 來解決上述的問題:

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

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

  
  

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

怎么辦?

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

首先,Safari 在10.1開始支持JS模塊, 但不支持nomodule屬性。值得慶幸的是,Sam找到了一種方法,可以通過Safari 10和11中非標準的beforeload事件來模擬 nomodule, 也就是可以認為Safari 10.1開始是可以支持module/nomodule模式

選項1: 動態(tài)加載

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

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

  


  
  

然而,這個解決方案必須等待進行‘石蕊試驗’模塊script執(zhí)行完成, 才能開始注入script。這是因為

看起來已經很完美了,還有什么問題呢?我們還沒考慮預加載(preloading)

這個有點蛋疼, 因為一般瀏覽器只會靜態(tài)地掃描HTML,然后查找它可以預加載的資源。 我們上面介紹的模塊加載器是完全動態(tài)的,所以瀏覽器在沒有運行我們的代碼之前,是沒辦法發(fā)現(xiàn)我們要預加載現(xiàn)代還是傳統(tǒng)的Javascript資源的。

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

  
  
  

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

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

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

大概代碼如下:

  
  
  

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

選項2: 用戶代理嗅探

我辦法拿出一個簡潔的代碼示例,因為用戶代理檢測不在本文的范圍之內,推薦閱讀這篇Smashing Magazine文章

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

對于那些已經在使用服務端渲染的網站來說,用戶代理嗅探是一個比較有效的解決方案

選項 3:不考慮舊版本瀏覽器

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

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

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

  


  


  
  
  
選項 4: 使用條件包

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

  


  
  

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

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

你應該怎么做?

答案取決于你的使用場景, 選擇和你們的架構匹配的選項:
如果你的應用只是客戶端渲染, 而且你的HTML不超過一個

閱讀需要支付1元查看
<