建構在所有主要瀏覽器上都能順利運作的網站,是開放式網路生態系統的核心宗旨。不過,這表示您必須額外進行工作,確保您編寫的所有程式碼都能在您要指定的每個瀏覽器中支援。如果您想使用新的 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,這是在不同工具之間共用的開放原始碼設定,用於指定瀏覽器。如需相容查詢的完整清單,請參閱瀏覽器清單說明文件。另一個選項是使用 .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 提供意見。