Study notes for ES6 transpiling & polyfill.
若須在 IE 上支援 ES6,則必須:
- 導入 polyfill 函式庫來實現新的原生 API。
<B>
- 使用 transpiler 來將 ES6 語法轉譯為 ES5 語法。
<C>
Reference
- Polyfill:用於實現瀏覽器並不支援的原生 API 的程式碼。
- Polyfill 是 shim 的一種,情境限制在瀏覽器 API 上。Polyfill 是一個用於瀏覽器 API 上的 shim。
- 一般實現的作法為:檢查瀏覽器對某 API 的支援度,若不支援,則載入對應的 polyfill 來實現該 API。
- core-js
<B-1>
- Polyfill.io
<B-2>
Reference
-
應用最廣泛的 polyfill 函式庫,被許多套件引用作為 polyfill 核心(如 Babel)。
-
可彈性引入需要的 polyfill。
-
可避免變動到全域命名空間。
-
安裝:
// global version npm install --save core-js@3.0.1 // version without global namespace pollution npm install --save core-js-pure@3.0.1 // bundled global version npm install --save core-js-bundle@3.0.1
Reference
- 自動化 polyfill js 打包線上服務。
- 使用其所提供的 API get 資源,將欲支援的功能作為參數傳遞,即可獲得適用於該瀏覽器所需的所有 polyfill minified bundle 檔。
- 優點:
- 省事
- 根據當下所使用的瀏覽器自動偵測,省去其他瀏覽器的 polyfill。
- 缺點:
- 站外資源無法控管(解法:下載其 GitHub 程式,部署到自己的 server。)
- 多一次額外的 request
Reference
- Babel
<C-1>
- Traceur
<C-2>
Reference
- Babel 採用 npm,預設是在支援 CommonJS
require
語法的 runtime 下執行模組載入。如要在此架構下作為 production 打包 / 運行,需要其他打包工具如 webpack。 - Setup & Transpiling
<C-1-1>
- Polyfill
<C-1-2>
- Configuration
<C-1-3>
- Babel setup with C# / .NET
<C-1-4>
Reference
- 安裝:使用 npm 安裝 core library
@babel/core
。 - Transpiling:
-
by JS require (CommonJS API):
const babel = require("@babel/core"); babel.transform("code", optionsObject);
-
by CLI tool:
npm install --save-dev @babel/cli
@babel/cli
: babel command line tool./node_modules/.bin/babel src --out-dir lib
將
src
資料夾下的程式碼轉譯到lib
資料夾下。 但此指令需要額外的參數來定義應如何轉譯程式碼,否則程式碼在上述轉譯後,與原始碼並無差別。(見<Plugins>
&<Presets>
。)
-
- Plugins:
-
用來指示 Babel 如何轉譯原始碼的小型 JS 程式。
-
可自訂。
-
用於將 ES6+ 箭頭函式轉譯為 ES5 語法的 Babel 官方 plugin:
@babel/plugin-transform-arrow-functions
。npm install --save-dev @babel/plugin-transform-arrow-functions ./node_modules/.bin/babel src --out-dir lib --plugins=@babel/plugin-transform-arrow-functions
-
- Presets:
- 預設好的 plugin 組合。
- 可自訂。
@babel/preset-env
:包含所有支援現代 JS 語法 plugin 的 Babel 官方 preset。搭配 browserlist 可以指定瀏覽器支援版本,同時支援 polyfill 功能<C-1-2-2>
。- 可以設定參數,只載入特定 plugin。
- stage:過新的 preset,可能仍在草案階段。分成 0-4 五個階段。
- 安裝:
-
by CLI tool:
npm install --save-dev @babel/preset-env ./node_modules/.bin/babel src --out-dir lib --presets=@babel/env
-
by Configuration: 在專案根目錄建立
babel.config.js
設定檔。const presets = [ [ "@babel/env", { targets: { edge: "17", firefox: "60", chrome: "67", safari: "11.1", } }, ], ]; module.exports = { presets };
現在
env
preset 將只會載入目標瀏覽器不支援的轉譯 plugin。
-
Reference
- Babel 使用 core-js 來實現 polyfill,與之相關的套件分為三個:
- @babel/polyfill
<C-1-2-1>
- @babel/preset-env
<C-1-2-2>
- @babel/runtime
<C-1-2-3>
- @babel/polyfill
- Tanspile + Polyfill:
- 在舊版,polyfill 跟 transpile 是分開設定的。因此若設定使用
babel-preset-es2015
,預設只轉譯語法,需額外引入babel-polyfill
才會加入 polyfill 功能。 - Babel 7 推出了
@babel/preset-env
,棄用了以年為單位的 preset(babel-preset-es2015
、babel-preset-es2016
、babel-preset-es2017
、babel-preset-latest
);使用@babel/preset-env
同時就會引入core-js
,意味著不須再額外引入@babel/polyfill
,並可直接在@babel/preset-env
中設定是否加入 polyfill 功能。<C-1-2-2>
- 在舊版,polyfill 跟 transpile 是分開設定的。因此若設定使用
Reference
@babel/polyfill
包含 core-js 的穩定功能(全域版、無 ES 草案) 和一個客製化的 regenerator runtime。- 停留在版本
core-js@2
,基本上已不建議使用。 - 若不需要 instance methods (ex. Array.prototype.includes),可改用 transform runtime plugin,避免更動全域 scope。
<C-1-2-3>
- 安裝:
Polyfill 必須要在原始碼之前先執行,因此要安裝在正式環境下。
npm install --save @babel/polyfill
Reference
- 使用 core-js 全域版。
- 利用
useBuiltIns
屬性來設定是否引入 polyfill 功能並自動最佳化。useBuiltIns: 'entry'
:依據 JS 進入點的core-js
設定,自動替換成目標環境所需的 polyfill 模組。useBuiltIns: 'usage'
:檢查程式碼,尋找目標環境所缺少的功能,並只引入需要的 polyfill。- 預設引入穩定功能的 polyfill。
- 小風險:由於 Babel 無法判斷程式碼中的資料型態,因此有可能載入錯誤的 polyfill。欲避免此風險,可使用
useBuiltIns: 'entry'
,或手動引入每個 polyfill。
useBuiltIns: 'disable'
:不使用 polyfill。(預設)
- 建議設置
corejs
屬性來指定 core-js 版本。例如:corejs: '3.0'
。- 如不指定版本,目前預設為引用
core-js v2.x
。使用core-js v2.x
需搭配安裝@babel/polyfill
方能正確引用core-js
。
- 如不指定版本,目前預設為引用
Reference
- 共用生成的 helper code:Babel 在轉譯過程中,會生成許多 helper 通用程式碼;這些程式碼存在於轉譯後的各個模組中,但其實內容完全相同可共用。這個模組讓所有 helper 關連到
@babel/runtime
模組,避免轉譯後重複宣告。 - 創造出沙盒環境:實現
core-js-pure
功能,自動將新的 JS 語法取代成從core-js
引入的版本,避免變動全域命名空間。- 適用於函式庫開發。
- 預設使用穩定功能的 polyfill。
Reference
- 有兩種設定檔格式,可同時或單獨使用。
- Project-wide:
babel.config.js
- 放在與
package.json
相同的根目錄下。Babel 在轉譯時會自動在此根目錄中搜尋此設定檔。 - 適用於通用設定;能使
node_modules
下的所有 plugin 和 preset 輕鬆套用設定。
- 放在與
- File-relative:
.babelrc
/.babelrc.js
/ 在package.json
檔案中設定babel
屬性- Babel 在轉譯時會從轉譯的文件向上搜尋設定檔,並由下往上合併、 override 設定檔。
- 只會套用到所屬套件中的檔案
- Project-wide:
Reference
- Standalone:Babel can be imported via
<script>
and run as an online transpiler.- The JS code to be transpiled should be used with
<script type='text/babel'>
. - The code transpiled will be inserted after the original code as another
<script>
snippet. - Online-transpiling incurs time cost for page loading, thus only suits for development phase like prototyping.
- The JS code to be transpiled should be used with
- ASP.NET MVC @ VS:Babel in VS is usually bundled for React feature.
Analysis: Integration with VS
Reference
Reference