使用 Polyfill 而不再是 bable 來實踐js新特性


現狀

我們想要用 ES6 語法來寫 JavaScript。然而由於我們需要兼容老版本的瀏覽器,那些瀏覽器不支持 ES6,我們需要解決這個問題。

有一個標准的做法是:寫 ES6 代碼 → 將所有代碼編譯成 ES5 的(比如通過 Babel)→ 再將編譯后的代碼加載到瀏覽器執行。

這可能已經不再是最有效率的方式了。因為用這種方式,我們強制最新的瀏覽器運行舊代碼,實際上它們完全可以運行最新的代碼。它們支持 ES6,我們難道不能直接給它們 ES6 代碼嗎?

改進方式

有一個 polyfill 項目叫做 Polyfill.io API,它可以通過 polyfill 方式在客戶端執行 ES6 代碼。

它也實現了一些 HTML 特性的 polyfill,比如 <picture> 元素。

下面是他們網站的描述:

Polyfill.io 讀取每個請求的 User-Agent(UA) 頭,並生成適合於該瀏覽器的 polyfill ,基於你的應用所使用的特性發回必要的代碼。[...]

Financial Times 在開發和維護這個項目,所以我們能確信這個項目可以持續更新下去,不會死掉。

有一點需要明白:Polyfill.io 沒有提供語法糖支持。比如 類、增強的對象字面量,以及箭頭函數之類的特性。對那些代碼,你仍然需要進行編譯。

配置 Polyfill.io

Adding Polyfill.io to your project can be this simple. Add the CDN-hosted script to your page:

要添加 Polyfill.io 到你的項目里非常簡單。將托管在 CDN 的腳本添加到你的頁面上:

`<script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>`

運行腳本將返回 UA 和你想要的特性。

  1.  
    UA detected: chrome/ 56.0.0
  2.  
    Features requested: default

修改請求參數

它提供了一堆選項 來自定義你要返回的特性。

Features

該參數指定需要 polyfill 的瀏覽器特性。多個特性名之間用逗號分隔。允許使用的特性明在 瀏覽器和特性 頁中列出。

`<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=fetch"></script>`

在 Safari 10 下,腳本返回內容如下:

  1.  
    Features requested: fetch
  2.  
     
  3.  
    - setImmediate, License: CC0 (required by "Promise", "fetch")
  4.  
    - fetch

如果一個特性,比如 fetch 依賴於另一個特性比如 Promise,Polyfill.io 會自動加載依賴。

Flags

  • always - Polyfill 將始終被包含,不管 UA 中指出的瀏覽器是否已經支持該特性。
  • gated - 通過特性檢測來判斷 Polyfill,只有在瀏覽器原生 API 不支持這些特性的情況下才返回並執行 Polyfill。
`<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=fetch&flags=gated"></script>`

Callback

Polyfill 腳本加載完成之后要執行的函數名。這是最簡單的在 polyfill 加載完成后觸發你自己的代碼的方式,這樣 polyfill 服務可以更容易通過 async 和 defer 屬性被異步加載。

存在的問題

聽起來很好,但是仍然不完美。

最新的瀏覽器不需要加載 ES5 代碼了,但是還需要通過服務器請求來檢測是否需要 polyfill。

這非常困擾我,因此我正在做一個小項目來改進它。

一個更好的方式

配置 dynamic polyfill

我創建了一個叫做 dynamic-polyfill 的 npm 包。它在發起任何服務端請求前檢測特性是否已經被原生支持。

它的配置看起來如下:

  1.  
    import polyfill from 'dynamic-polyfill'
  2.  
     
  3.  
    polyfill({
  4.  
    fills: 'fetch, Promise',
  5.  
    options: 'gated', // default: null
  6.  
    minify: false, // default: true
  7.  
    afterFill() {
  8.  
    main()
  9.  
    }
  10.  
    })
  11.  
     
  12.  
    function main() {
  13.  
    // app code here
  14.  
    }

簡單來說,它的執行過程如下:

檢測 [window.fetch, window.Promise] 是否存在。

如果存在,運行 afterFill() 回調。

如果它們不存在,創建一個 <script> 標簽,並且包含 async 屬性,將 Polyfill.io 鏈接插入,用參數中提供的選項去請求,並在它加載完成后執行 afterFill() 回調。

注意: 現在還沒有支持全部選項,只有那些最重要的項被支持。

腳本很小

由於這個模塊在壓縮后不到 1KB 大小,而且沒有任何依賴,對項目使用來說成本超低。

結論

為最新的瀏覽器寫不過時和有效率的 JavaScript,讓 Polyfill.io 去處理老版本的的瀏覽器,如果不必要,別發起額外的 HTTP 請求。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM