@babel/plugin-transform-runtime
一個可重複使用 Babel 注入的輔助程式碼的 plugin,以節省程式碼大小。
例如 "foobar".includes("foo")
等實例方法僅適用於 core-js@3
。如果您需要為其進行 polyfill,您可以直接匯入 "core-js"
或使用 @babel/preset-env
的 useBuiltIns
選項。
安裝
將其安裝為開發依賴項。
- npm
- Yarn
- pnpm
npm install --save-dev @babel/plugin-transform-runtime
yarn add --dev @babel/plugin-transform-runtime
pnpm add --save-dev @babel/plugin-transform-runtime
以及 @babel/runtime
作為生產依賴項(因為它是用於「執行階段」)。
- npm
- Yarn
- pnpm
npm install --save @babel/runtime
yarn add @babel/runtime
pnpm add @babel/runtime
轉換外掛通常僅用於開發,但執行階段本身會由您部署的程式碼依賴。有關更多詳細資訊,請參閱以下範例。
啟用此外掛時,不得設定 @babel/preset-env
中的 useBuiltIns
選項。否則,此外掛可能無法完全沙盒化環境。
原因?
Babel 使用非常小的幫手來處理常見功能,例如 _extend
。預設情況下,這將新增到每個需要它的檔案。這種重複有時是不必要的,特別是當您的應用程式分散在多個檔案時。
這就是 @babel/plugin-transform-runtime
外掛的用武之地:所有幫手都會參照模組 @babel/runtime
以避免在編譯輸出中重複。執行階段將編譯到您的建置中。
此轉換器的另一個目的是為你的程式碼建立一個沙盒環境。如果你直接匯入 core-js 或 @babel/polyfill 和它提供的內建函數,例如 Promise
、Set
和 Map
,它們會污染全域範圍。雖然這對應用程式或命令列工具來說可能沒問題,但如果你的程式碼是一個你打算發布給其他人使用的函式庫,或者你無法完全控制程式碼執行的環境,這就會變成一個問題。
轉換器會將這些內建函數別名設為 core-js
,這樣你就可以無縫使用它們,而不需要要求多重載入。
請參閱 技術詳細資料 部分,以瞭解有關此運作方式和發生的轉換類型的更多資訊。
用法
使用設定檔(建議)
沒有選項
{
"plugins": ["@babel/plugin-transform-runtime"]
}
有選項(及其預設值)
{
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"absoluteRuntime": false,
"corejs": false,
"helpers": true,
"regenerator": true,
"version": "7.0.0-beta.0"
}
]
]
}
此外掛程式預設假設所有可多重載入的 API 都會由使用者提供。否則需要指定 corejs
選項。
透過 CLI
babel --plugins @babel/plugin-transform-runtime script.js
透過 Node API
require("@babel/core").transformSync("code", {
plugins: ["@babel/plugin-transform-runtime"],
});
選項
corejs
false
、2
、3
或 { version: 2 | 3, proposals: boolean }
,預設為 false
。
例如:['@babel/plugin-transform-runtime', { corejs: 3 }],
歷史
版本 | 變更 |
---|---|
v7.4.0 | 支援 { proposals: boolean } |
指定數字將會改寫需要可多重填充 API 的輔助函式,以參照 core-js
的那個(主要)版本中的輔助函式。請注意,corejs: 2
僅支援全域變數(例如:Promise
)和靜態屬性(例如:Array.from
),而 corejs: 3
也支援執行個體屬性(例如:[].includes
)。
預設情況下,@babel/plugin-transform-runtime
不會多重填充建議。如果您正在使用 corejs: 3
,您可以透過啟用 proposals: true
選項來選擇加入。
此選項需要變更依賴項,以提供必要的執行時期輔助函式
corejs 選項 | 安裝指令 |
---|---|
false | npm install --save @babel/runtime |
2 | npm install --save @babel/runtime-corejs2 |
3 | npm install --save @babel/runtime-corejs3 |
helpers
boolean
,預設為 true
。
切換內嵌 Babel 輔助函式(classCallCheck
、extends
等)是否以呼叫 @babel/runtime
(或等效套件)取代。
如需更多資訊,請參閱 輔助函式別名。
moduleName
歷史
版本 | 變更 |
---|---|
v7.24.0 | 已新增 moduleName 選項 |
字串
,預設為 @babel/runtime
。
此選項控制 @babel/plugin-transform-runtime
在注入匯入時將使用哪個 helper 套件。其使用下列優先順序
moduleName
選項(如果已指定)- 任何
babel-plugin-polyfill-*
外掛建議的 helper 模組babel-plugin-polyfill-corejs3
建議@babel/runtime-corejs3
babel-plugin-polyfill-corejs2
建議@babel/runtime-corejs2
- 備援為
@babel/runtime
請注意,指定 corejs
選項會在內部啟用對應的 babel-plugin-polyfill-corejs*
外掛,因此會影響最終的模組名稱。
polyfill
此選項已在 v7 中移除。
regenerator
boolean
,預設為 true
。
切換是否將產生器函式轉換為使用不會污染全域範圍的 regenerator 執行階段。
如需更多資訊,請參閱 Regenerator 別名。
useBuiltIns
此選項已在 v7 中移除。
useESModules
此選項已棄用,且將於 Babel 8 中移除:從版本 7.13.0
開始,@babel/runtime
的 package.json
使用 "exports"
選項自動在 CJS 和 ESM 輔助函式之間進行選擇。
boolean
,預設為 false
。
歷史
版本 | 變更 |
---|---|
v7.13.0 | 此選項已棄用 |
啟用時,轉換將使用不會透過 @babel/plugin-transform-modules-commonjs
執行的輔助函式。這允許在 webpack 等模組系統中進行較小的建置,因為它不需要保留 commonjs 語意。
例如,以下是停用 useESModules
的 classCallCheck
輔助函式
exports.__esModule = true;
exports.default = function(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
而啟用時
export default function(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
absoluteRuntime
boolean
或 string
,預設為 false
。
這允許使用者在整個專案中廣泛執行 transform-runtime
。預設情況下,transform-runtime
直接從 @babel/runtime/foo
匯入,但這只有在 @babel/runtime
位於正在編譯檔案的 node_modules
中時才有效。這可能會對巢狀 node_modules
、npm 連結模組或位於使用者專案外部的 CLI 造成問題。為了避免擔心如何解析執行時期模組的位置,這允許使用者事先解析執行時期,然後將執行時期的絕對路徑插入輸出程式碼中。
如果檔案編譯供稍後使用,則不建議使用絕對路徑,但在編譯檔案然後立即使用的環境中,它們可能非常有幫助。
您可以在這裡閱讀更多關於設定外掛選項的資訊
version
預設情況下,transform-runtime 假設已安裝 @babel/runtime@7.0.0
。如果您已安裝或列為相依項的 @babel/runtime
(或其核心對應項,例如 @babel/runtime-corejs3
) 的後續版本,transform-runtime 可以使用更進階的功能。
例如,如果您相依於 @babel/runtime-corejs2@7.7.4
,您可以使用以下指令轉譯您的程式碼
{
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"absoluteRuntime": false,
"corejs": 2,
"version": "^7.7.4"
}
]
]
}
這將產生較小的套件大小。
技術細節
transform-runtime
轉譯器外掛程式執行三項工作
- 當您使用產生器/非同步函數時,自動需要
@babel/runtime/regenerator
(可透過regenerator
選項切換)。 - 必要時,可以使用
core-js
作為輔助程式,而不是假設使用者會使用多重填充 (可透過corejs
選項切換) - 自動移除內嵌的 Babel 輔助程式,並改用模組
@babel/runtime/helpers
(可透過helpers
選項切換)。
這實際上是什麼意思?基本上,您可以使用內建函數,例如 Promise
、Set
、Symbol
等,並使用所有需要多重填充的 Babel 功能,而不會造成全域污染,這使其非常適合用於函式庫。
請務必將 @babel/runtime
包含為相依項。
產生器別名
每當您使用產生器函數或非同步函數時
function* foo() {}
會產生以下內容
"use strict";
var _marked = [foo].map(regeneratorRuntime.mark);
function foo() {
return regeneratorRuntime.wrap(
function foo$(_context) {
while (1) {
switch ((_context.prev = _context.next)) {
case 0:
case "end":
return _context.stop();
}
}
},
_marked[0],
this
);
}
這並非理想,因為它依賴於包含 regenerator 執行時期,這會污染全域範圍。
然而,使用 runtime
轉換器,它會編譯為
"use strict";
var _regenerator = require("@babel/runtime/regenerator");
var _regenerator2 = _interopRequireDefault(_regenerator);
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : { default: obj };
}
var _marked = [foo].map(_regenerator2.default.mark);
function foo() {
return _regenerator2.default.wrap(
function foo$(_context) {
while (1) {
switch ((_context.prev = _context.next)) {
case 0:
case "end":
return _context.stop();
}
}
},
_marked[0],
this
);
}
這表示您可以使用 regenerator 執行時期,而不會污染目前的環境。
core-js
別名
有時您可能想要使用新的內建函式,例如 Map
、Set
、Promise
等。您使用這些函式的唯一方法通常是包含會造成全域污染的 polyfill。
這是使用 corejs
選項。
外掛程式轉換下列內容
var sym = Symbol();
var promise = Promise.resolve();
var check = arr.includes("yeah!");
console.log(arr[Symbol.iterator]());
為下列內容
import _getIterator from "@babel/runtime-corejs3/core-js/get-iterator";
import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes";
import _Promise from "@babel/runtime-corejs3/core-js-stable/promise";
import _Symbol from "@babel/runtime-corejs3/core-js-stable/symbol";
var sym = _Symbol();
var promise = _Promise.resolve();
var check = _includesInstanceProperty(arr).call(arr, "yeah!");
console.log(_getIterator(arr));
這表示您可以無縫使用這些原生內建函式和方法,而不用擔心它們從何而來。
注意:實例方法,例如 "foobar".includes("foo")
,僅在使用 corejs: 3
時才會運作。
輔助函式別名
Babel 通常會將輔助函式置於檔案頂端,以執行常見任務,避免在目前檔案中重複程式碼。有時這些輔助函式會變得有點龐大,並在檔案間增加不必要的重複。runtime
轉換器會將所有輔助函式呼叫替換為一個模組。
這表示下列程式碼
class Person {}
通常會變成
"use strict";
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
var Person = function Person() {
_classCallCheck(this, Person);
};
然而,runtime
轉換器會將它變成
"use strict";
var _classCallCheck2 = require("@babel/runtime/helpers/classCallCheck");
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : { default: obj };
}
var Person = function Person() {
(0, _classCallCheck3.default)(this, Person);
};