跳到主要內容

@babel/plugin-transform-runtime

一個可重複使用 Babel 注入的輔助程式碼的 plugin,以節省程式碼大小。

注意

例如 "foobar".includes("foo") 等實例方法僅適用於 core-js@3。如果您需要為其進行 polyfill,您可以直接匯入 "core-js" 或使用 @babel/preset-envuseBuiltIns 選項。

安裝

將其安裝為開發依賴項。

npm install --save-dev @babel/plugin-transform-runtime

以及 @babel/runtime 作為生產依賴項(因為它是用於「執行階段」)。

npm install --save @babel/runtime

轉換外掛通常僅用於開發,但執行階段本身會由您部署的程式碼依賴。有關更多詳細資訊,請參閱以下範例。

危險

啟用此外掛時,不得設定 @babel/preset-env 中的 useBuiltIns 選項。否則,此外掛可能無法完全沙盒化環境。

原因?

Babel 使用非常小的幫手來處理常見功能,例如 _extend。預設情況下,這將新增到每個需要它的檔案。這種重複有時是不必要的,特別是當您的應用程式分散在多個檔案時。

這就是 @babel/plugin-transform-runtime 外掛的用武之地:所有幫手都會參照模組 @babel/runtime 以避免在編譯輸出中重複。執行階段將編譯到您的建置中。

此轉換器的另一個目的是為你的程式碼建立一個沙盒環境。如果你直接匯入 core-js@babel/polyfill 和它提供的內建函數,例如 PromiseSetMap,它們會污染全域範圍。雖然這對應用程式或命令列工具來說可能沒問題,但如果你的程式碼是一個你打算發布給其他人使用的函式庫,或者你無法完全控制程式碼執行的環境,這就會變成一個問題。

轉換器會將這些內建函數別名設為 core-js,這樣你就可以無縫使用它們,而不需要要求多重載入。

請參閱 技術詳細資料 部分,以瞭解有關此運作方式和發生的轉換類型的更多資訊。

用法

沒有選項

babel.config.json
{
"plugins": ["@babel/plugin-transform-runtime"]
}

有選項(及其預設值)

babel.config.json
{
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"absoluteRuntime": false,
"corejs": false,
"helpers": true,
"regenerator": true,
"version": "7.0.0-beta.0"
}
]
]
}

此外掛程式預設假設所有可多重載入的 API 都會由使用者提供。否則需要指定 corejs 選項。

透過 CLI

Shell
babel --plugins @babel/plugin-transform-runtime script.js

透過 Node API

JavaScript
require("@babel/core").transformSync("code", {
plugins: ["@babel/plugin-transform-runtime"],
});

選項

corejs

false23{ 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 選項安裝指令
falsenpm install --save @babel/runtime
2npm install --save @babel/runtime-corejs2
3npm install --save @babel/runtime-corejs3

helpers

boolean,預設為 true

切換內嵌 Babel 輔助函式(classCallCheckextends 等)是否以呼叫 @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/runtimepackage.json 使用 "exports" 選項自動在 CJS 和 ESM 輔助函式之間進行選擇。

boolean,預設為 false

歷史
版本變更
v7.13.0此選項已棄用

啟用時,轉換將使用不會透過 @babel/plugin-transform-modules-commonjs 執行的輔助函式。這允許在 webpack 等模組系統中進行較小的建置,因為它不需要保留 commonjs 語意。

例如,以下是停用 useESModulesclassCallCheck 輔助函式

JavaScript
exports.__esModule = true;

exports.default = function(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};

而啟用時

JavaScript
export default function(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}

absoluteRuntime

booleanstring,預設為 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,您可以使用以下指令轉譯您的程式碼

babel.config.json
{
"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 選項切換)。

這實際上是什麼意思?基本上,您可以使用內建函數,例如 PromiseSetSymbol 等,並使用所有需要多重填充的 Babel 功能,而不會造成全域污染,這使其非常適合用於函式庫。

請務必將 @babel/runtime 包含為相依項。

產生器別名

每當您使用產生器函數或非同步函數時

JavaScript
function* foo() {}

會產生以下內容

JavaScript
"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 轉換器,它會編譯為

JavaScript
"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 別名

有時您可能想要使用新的內建函式,例如 MapSetPromise 等。您使用這些函式的唯一方法通常是包含會造成全域污染的 polyfill。

這是使用 corejs 選項。

外掛程式轉換下列內容

JavaScript
var sym = Symbol();

var promise = Promise.resolve();

var check = arr.includes("yeah!");

console.log(arr[Symbol.iterator]());

為下列內容

JavaScript
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 轉換器會將所有輔助函式呼叫替換為一個模組。

這表示下列程式碼

JavaScript
class Person {}

通常會變成

JavaScript
"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 轉換器會將它變成

JavaScript
"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);
};