建構在所有主要瀏覽器上都能順利運作的網站,是開放式網路生態系統的核心宗旨。不過,這表示您必須額外進行工作,確保您編寫的所有程式碼都能在您打算指定的每個瀏覽器中運作。如果您想使用新的 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 提供意見。