Since @babel/polyfill
is deprecated after Babel 7.4, both @babel/preset-env
and plugin-transform-runtime
can set corejs
to handle polyfill
.
The main reasons for
@babel/polyfill
deprecation are:
- This package simply introduces stable core-js and regenerator-runtime/runtime, the latter of which can be replaced by the plugin @babel/plugin-transform-regenerator.
- This package does not have a smooth transition from core-js@2 to core-js@3.
Introduction to Babel
Simply put, Babel
is a compiler that converts code written in ECMAScript 2015+
syntax into backwards-compatible JavaScript
syntax so that it can run in various environments such as old and new browsers. The Babel code conversion function is implemented in the form of plugin
, plugin
is a small JavaScript program.
A preset
can be thought of as a set of Babel plugins or shareable modules configured by options
.
- plugins run before presets;
- plugins are executed sequentially from front to back;
- presets are executed in reverse order according to the sorting order;
Babel mainly implements two functions:
- Convert the new syntax. Implement the new version of js syntax with the old version to run in the corresponding environment, such as arrow functions;
Convert the new API. Patch (also known as polyfill) the old runtime to use features defined in the new js but provided in the old runtime, including three categories:
- Newly defined built-in objects such as
Promise
- Newly added static methods of the original built-in objects, such as
Array.from
- Newly added instance methods of the original built-in objects, such as
Array.prototype.includes
- Newly defined built-in objects such as
preset-env
preset-env
can convert both new syntax and new API
through configuration. The polyfill
of preset-env
will pollute the global environment.
target
This field can fill in the query string of browserslist
. It is officially recommended to use the .browserslistrc
file to specify the compiled target
. This configuration file can also share configuration with tools such as autoprefixer
and stylelint
. Therefore, it is not recommended to use targets
directly in the preset-env
configuration of .babelrc
.
If you need to configuretargets
here separately, specifyignoreBrowserslistConfig
inpreset-env
astrue
to ignore the configuration items of.browserslistrc
.
useBuiltIns
Whether to use its polyfill
feature (core-js for global environment). There are three values:
-
false
: Default value. Do not usepreset-env
to implementpolyfills
without activelyimport
, and only use its default syntax conversion function. If you use the default value offalse
, you should avoid introducingpolyfill
in the entry file, making the package size too large. entry
: You need to manually introducepolyfill
at the entry point. According to the configuration of the browser target environment (targets
), introducepolyfill
modules that are not currently supported by all browsers, regardless of whether they are used in the project or not.import "core-js/proposals/string-replace-all"
-
usage
: There is no need to manually introducepolyfill
in the entry file,Babel
will automatically injectpolyfill
according to the code usage, so that the packaging volume will be relatively reduced when packaging.
corejs
Configure core-js, the default value is "2.0". This option is only valid when used with useBuiltIns: usage
or useBuiltIns: entry
.
core-js : A modular standard library for JavaScript, with Promise
, Symbol
, Iterator
, and many other features that lets you load only the functionality you need.
- version: [string] version number;
- proposals: [boolean] Whether to implement the features in the proposal;
// .babelrc { "presets": [ [ "@babel/preset-env", { "targets": { "chrome": "80" // 推荐使用 .browserslistrc }, "useBuiltIns": "usage", "corejs": { "version": 3, // 2 和 3 版本都需要手动安装库:yarn add core-js@3 "proposals": false } } ] ] }
plugin-transform-runtime
plugin-transform-runtime
mainly does three things:
- When developers use asynchronous or generators,
@babel/runtime/regenerator
is automatically introduced, and developers do not need to do additional introductions in the entry file; Dynamically introduce
polyfill
to provide a sandbox environment to avoid pollution of the global environment;If you directly import core-js or @babel/polyfill and the built-in components it provides such as Promise, Set and Map, these will pollute the global. While this doesn't affect applications or command-line tools, problems can arise if the code is a library that is meant to be released to others for use, or if there is no precise control over the environment in which the code will run.
- All helpers helper modules will reference the module @babel/runtime to avoid duplication in compilation output and reduce packaging size;
corejs
Configuration value: false, 2, or { version: number, proposals: boolean }
, the default value is false.
corejs | Installation advice |
---|---|
false | npm install --save @babel/runtime |
2 | npm install --save @babel/runtime-corejs2 |
3 | npm install --save @babel/runtime-corejs3 |
helpers
The configuration value is boolean type, the default value is true.
Whether to replace inline Babel helpers (classCallCheck, extends, etc.) with calls to moduleName.
regenerator
The configuration value is boolean type, the default value is true.
Whether to convert generator functions to use a regenerator runtime that does not pollute the global scope.
useESModules
The configuration value is boolean type, the default value is false.
When enabled, transforms will use helpers instead of @babel/plugin-transform-modules-commonjs. This allows for smaller builds in module systems like webpack, since it doesn't need to preserve commonjs semantics.
Analysis of usage scenarios and examples
Both @babel/preset-env
and plugin-transform-runtime
can be set to use corejs
to process polyfill
. Both have their own usage scenarios, and different configurations can be used during project development and class library development.
Don't configure core-js for both at the same time to avoid complex undesirable consequences.
Project Development
useBuiltIns
uses usage
. plugin-transform-runtime
only uses its feature of removing inline multiplexed helper functions to reduce packaging size.
{ "presets": [ [ "@babel/preset-env", { "useBuiltIns": "usage", "corejs": { "version": 3, "proposals": false } } ] ], "plugins": [ [ "@babel/plugin-transform-runtime", { "corejs": false } ] ] }
Class library development
For class library development, try not to use polyfill
that pollute the global environment, so @babel/preset-env
only plays the function of syntax conversion, and polyfill
are handled by plugin-transform-runtime
. It is recommended to use core-js@3
, and do not use non-standardized characteristics.
{ "presets": ["@babel/preset-env"], "plugins": [ [ "@babel/plugin-transform-runtime", { "corejs": { "version": 3, "proposals": false }, "useESModules": true } ] ] }
Packaging Analysis
The test code is as follows:
// syntax class Person {} typeof Person const array = [1, 2, 3] const fun = () => {} // api const a = Array.isArray([3, 5, 8]) const b = array.map(itm => itm * 2) const p1 = Promise.resolve(true) const p2 = Promise.reject(false) Promise.allSettled([p1, p2]).then(() => { console.log('then') }).catch(() => { console.log('catch') }).finally(() => { console.log('finally') })
Configure core-js via preset-env:
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); require("core-js/modules/es.array.is-array.js"); require("core-js/modules/es.array.map.js"); require("core-js/modules/es.object.to-string.js"); require("core-js/modules/es.promise.js"); require("core-js/modules/es.promise.finally.js"); require("core-js/modules/es.array.iterator.js"); require("core-js/modules/esnext.promise.all-settled.js"); require("core-js/modules/es.string.iterator.js"); require("core-js/modules/web.dom-collections.iterator.js"); var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); // syntax var Person = /*#__PURE__*/(0, _createClass2["default"])(function Person() { (0, _classCallCheck2["default"])(this, Person); }); (0, _typeof2["default"])(Person); var array = [1, 2, 3]; var fun = function fun() {}; // api var a = Array.isArray([3, 5, 8]); var b = array.map(function (itm) { return itm * 2; }); var p1 = Promise.resolve(true); var p2 = Promise.reject(false); Promise.allSettled([p1, p2]).then(function () { console.log('then'); })["catch"](function () { console.log('catch'); })["finally"](function () { console.log('finally'); });
Configure core-js through plugin-transform-runtime:
"use strict"; var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault"); var _isArray = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/array/is-array")); var _map = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/map")); var _promise = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/promise")); var _typeof2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/typeof")); var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/createClass")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/classCallCheck")); // syntax var Person = /*#__PURE__*/(0, _createClass2["default"])(function Person() { (0, _classCallCheck2["default"])(this, Person); }); (0, _typeof2["default"])(Person); var array = [1, 2, 3]; var fun = function fun() {}; // api var a = (0, _isArray["default"])([3, 5, 8]); var b = (0, _map["default"])(array).call(array, function (itm) { return itm * 2; }); var p1 = _promise["default"].resolve(true); var p2 = _promise["default"].reject(false); _promise["default"].allSettled([p1, p2]).then(function () { console.log('then'); })["catch"](function () { console.log('catch'); })["finally"](function () { console.log('finally'); });
Through the code analysis after packaging, unnecessary polyfills will be introduced in the way of preset-env, and only the polyfills required by the current page will be introduced in the way of plugin-transform-runtime.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。