為新型瀏覽器提供新程式碼,加快網頁載入速度

打造在所有主要瀏覽器上都能正常運作的網站,是開放網路生態系統的核心原則。不過,這意味著請進一步確保,您計畫指定的每個瀏覽器都支援您編寫的所有程式碼。如要使用新的 JavaScript 語言功能,請將這些功能轉換為與回溯相容的格式,以便支援尚未支援這類功能的瀏覽器。

Babel 是最常用來編譯程式碼的工具,它包含較新語法的程式碼,讓不同瀏覽器和環境 (例如 Node) 能理解。本指南假設您使用的是 Babel,因此如需相關操作說明,請按照設定操作說明將其納入應用程式。如果您使用 Webpack 做為應用程式的模組組合器,請在 Build Systems 中選取 webpack

如要使用 Babel 只轉譯使用者所需的資料,您需要:

  1. 找出要指定的瀏覽器。
  2. 搭配適當的瀏覽器目標使用 @babel/preset-env
  3. 使用 <script type="module"> 即可停止將轉碼後的程式碼傳送至不需要該程式碼的瀏覽器。

找出要指定的瀏覽器

在開始修改應用程式程式碼的轉譯方式之前,您需要先識別哪些瀏覽器可存取應用程式。您可以分析使用者正在使用哪些瀏覽器,以及您打算指定的目標瀏覽器,藉此做出明智的決定。

使用 @babel/preset-env

轉譯程式碼通常會導致檔案大小大於原始格式的檔案。盡量減少編譯的編譯量,即可縮減套件大小,進而提升網頁效能。

Babel 提供了數個包含外掛程式的預設版本,而不是新增特定外掛程式來選擇性編譯您使用的特定語言功能。使用 @babel/preset-env 直接加入要指定之瀏覽器所需的轉換和 polyfill。

在 Babel 設定檔 .babelrcpresets 陣列中加入 @babel/preset-env

{
 "presets": [
   [
     "@babel/preset-env",
     {
       "targets": ">0.25%"
     }
   ]
 ]
}

使用 targets 欄位指定您要納入的瀏覽器版本,方法是在 browsers 欄位中加入適當的查詢。@babel/preset-env 可與瀏覽器清單整合,這是不同工具之間用於指定瀏覽器的開放原始碼設定。如需相容查詢的完整清單,請參閱瀏覽器清單說明文件。另一種做法是使用 .browserslistrc 檔案列出您要指定的環境。

">0.25%" 值會指示 Babel 只加入支援瀏覽器佔全球用量超過 0.25% 所需的轉換。這可以確保套件不會針對極少數使用者使用的瀏覽器,納入不必要的轉譯程式碼。

在大多數情況下,這比使用以下設定更好:

  "targets": "last 2 versions"

"last 2 versions" 值會將每個瀏覽器的最後兩個版本的程式碼轉譯,這表示 Internet Explorer 等已停用的瀏覽器也能取得相關支援。如果不希望使用這些瀏覽器存取您的應用程式,這可能會使套件大小過大。

最後,您應該選取適當的查詢組合,只指定符合需求的瀏覽器。

啟用新型錯誤修正功能

@babel/preset-env 會將多個 JavaScript 語法功能分組為集合,並根據指定的瀏覽器啟用/停用這些功能。雖然這種做法可正常運作,但如果目標瀏覽器含有隻有一項功能的錯誤,整組語法功能都會轉換。這常會導致轉換的程式碼數量超出必要。

我們最初是以獨立預設設定開發,這是 @babel/preset-env 中的錯誤修正選項,可將某些瀏覽器中毀損的新型語法轉換為近似於這些瀏覽器未中斷的同等語法,藉此解決這個問題。這樣的結果就是幾乎與現代程式碼相同的現代化程式碼,稍微調整語法,確保程式碼在所有目標瀏覽器中都能相容。如要使用這項最佳化功能,請確認已安裝 @babel/preset-env 7.10 以上版本,然後將 bugfixes 屬性設為 true

{
 "presets": [
   [
     "@babel/preset-env",
     {
       "bugfixes": true
     }
   ]
 ]
}

在 Babel 8 中,bugfixes 選項預設為啟用。

使用 <script type="module">

JavaScript 模組 (或 ES 模組) 是所有主要瀏覽器支援的相對新功能。您可以使用模組建立指令碼,以便從其他模組匯入和匯出,但也可以與 @babel/preset-env 搭配使用,只指定支援這些模組的瀏覽器。

與其查詢特定瀏覽器版本或市佔率,請考慮在 .babelrc 檔案的 targets 欄位內指定 "esmodules" : true

{
   "presets":[
      [
         "@babel/preset-env",
         {
            "targets":{
               "esmodules": true
            }
         }
      ]
   ]
}

支援 JavaScript 模組的環境已支援許多使用 Babel 編譯的較新 ECMAScript 功能。因此,這可以簡化程序,確保只將經過轉譯的程式碼用於確實有需要的瀏覽器。

支援模組的瀏覽器會忽略含有 nomodule 屬性的指令碼。相反地,不支援模組的瀏覽器會忽略含有 type="module" 的指令碼元素。這表示您可以加入模組和已編譯的備用項。

在理想情況下,應用程式的兩個版本指令碼會如下所示:

  <script type="module" src="main.mjs"></script>
  <script nomodule src="compiled.js" defer></script>

支援模組會擷取及執行 main.mjs 並忽略 compiled.js 的瀏覽器。不支援模組的瀏覽器則會以相反方式執行。

如果您使用 webpack,可以在應用程式的兩個不同版本設定中,設定不同的目標:

  • 僅適用於支援模組的瀏覽器版本。
  • 包含編譯指令碼的版本,適用於任何舊版瀏覽器。因為翻譯需要支援更多種瀏覽器,所以檔案大小較大。

感謝 Connor Clark 和 Jason Miller 撰寫評論