在所有主要瀏覽器上順利運作的網站,是開放網路生態系統的核心原則。不過,這表示您必須額外確保所編寫的所有程式碼,都支援您打算鎖定的每個瀏覽器。如要使用新的 JavaScript 語言功能,您必須將這些功能轉譯為回溯相容的格式,供不支援這些功能的瀏覽器使用。
Babel 是最常用的程式碼編譯工具,可將含有新語法的程式碼編譯為不同瀏覽器和環境 (例如 Node) 可解讀的程式碼。本指南假設您使用 Babel,因此如果您尚未將 Babel 納入應用程式,請按照設定說明操作。如果您在應用程式中使用 webpack 做為模組打包工具,請在 Build Systems 中選取 webpack。
如要使用 Babel 僅轉譯使用者需要的內容,請按照下列步驟操作:
- 找出要指定的瀏覽器。
- 使用
@babel/preset-env,並指定適當的瀏覽器目標。 - 使用
<script type="module">停止將轉譯的程式碼傳送給不需要的瀏覽器。
找出要指定的瀏覽器
開始修改應用程式程式碼的轉譯方式前,請先找出存取應用程式的瀏覽器。分析使用者使用的瀏覽器,以及您打算指定的瀏覽器,做出明智的決定。
使用 @babel/preset-env
轉譯程式碼後產生的檔案,通常會比原始檔案大。盡量減少編譯量,即可縮減組合大小,進而提升網頁效能。
Babel 提供多個預設集,可將外掛程式組合在一起,不必納入特定外掛程式,即可選擇性地編譯所用的特定語言功能。使用 @babel/preset-env,只納入您打算鎖定的瀏覽器所需的轉換和 polyfill。
在 Babel 設定檔 .babelrc 的 presets 陣列中加入 @babel/preset-env:
{
"presets": [
[
"@babel/preset-env",
{
"targets": ">0.25%"
}
]
]
}
在「瀏覽器版本」targets欄位中,於「查詢」browsers欄位中加入適當的查詢,指定要納入哪些瀏覽器版本。@babel/preset-env
會與 browserslist 整合,這是不同工具之間共用的開放原始碼設定,用於指定瀏覽器。如需相容查詢的完整清單,請參閱 browserslist 說明文件。您也可以使用 .browserslistrc 檔案列出要指定的環境。
">0.25%" 值會告知 Babel,只納入支援全球使用率超過 0.25% 的瀏覽器所需的轉換。這樣可確保套件不會包含不必要的轉譯程式碼,以免傳送給使用人數極少的瀏覽器。
在大多數情況下,這種做法比使用下列設定更合適:
"targets": "last 2 versions"
"last 2 versions" 值會轉譯每個瀏覽器最近兩個版本的程式碼,因此支援已停用的瀏覽器,例如 Internet Explorer。如果您不希望使用者透過這些瀏覽器存取應用程式,這可能會不必要地增加套件大小。
最後,您應選取適當的查詢組合,只指定符合需求的瀏覽器。
啟用現代錯誤修正
@babel/preset-env 會將多個 JavaScript 語法功能分組為集合,並根據指定的目標瀏覽器啟用和停用這些功能。雖然這樣做效果不錯,但如果目標瀏覽器只有單一功能有錯誤,整個語法功能集合就會轉換。這通常會導致轉換的程式碼超出必要範圍。
原本是獨立預設值,但 @babel/preset-env 中的 bugfixes 選項可將部分瀏覽器中損壞的新式語法,轉換為這些瀏覽器中未損壞的最接近等效語法,藉此解決問題。結果幾乎完全相同,但會進行一些小幅度的語法調整,確保與所有目標瀏覽器相容。如要使用這項最佳化功能,請確認已安裝 @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 的審查。