The post was posted on my GitHub blog:Biu-blogWelcome to pay attention to ~

@babel/preset-env

The main function of @babel/preset-env is to run on the target platform based on the code generated by the Babel build. @babel/preset-env internally relies on a number of plugins: @babel/plugin-transform-*. The main job of these plugins is to convert the new ES syntax from the higher version to the lower version of the syntax as Babel handles the code. For example, @babel/plugin-transform-arrow-function is used to transform the syntax of arrow functions.

Basic configuration method:

// babel.config.json {"presets": [["@babel/preset-env", {// Preset related configuration}]]}

For Web-side projects or projects based on Electron, it is generally used with.browserListc (or the browsersList field in package.json) (to determine the final build platform).

Relative options configuration

useBuiltIns

“usage” | “entry” | false, defaults to false.

This configuration option also determines how @babel/preset-env refers to polyfills. When the configuration option is: usage or entry, @babel/preset-env directly creates a reference to the corre-js related module. So this also means that core-js will be resolved to the corresponding relative path and you need to make sure that core-js is installed in your project.

Since @babel/polyfill has been deprecated since version 7.4.0, it is recommended to configure the coreJS option directly and install core-JS directly in your project.

useBuiltIns: ‘entry’

Configuring this way needs to be injected into your business code:

import 'core-js/stable'
import 'regenerator-runtime/runtime'

As Babel processes the code, a new plugin will be introduced, and @babel/preset-env will introduce the required polyfill for the corresponding platform, depending on the configuration at target, or.browserlistrc:

In:

import 'core-js'

Out(different based on environment):

import "core-js/modules/es.string.pad-start"
import "core-js/modules/es.string.pad-end"

Note: actually here useBuiltIns:entryAnd the need to inject in the business codecore-jsandregenerator-runtime/runtimeIn terms of usage, injecting the corresponding package into the business code plays more of a placeholder role@babel/preset-envThen according to the different target platform to introduce the corresponding needspolyfillfile

In addition, if you import ‘core-js’, all ECMAScript features will be polyfilled during processing. If you only want to import some features, you can:

In:

import 'core-js/es/array'
import 'core-js/proposals/math-extensions'

Out:

import "core-js/modules/es.array.unscopables.flat";
import "core-js/modules/es.array.unscopables.flat-map";
import "core-js/modules/esnext.math.clamp";
import "core-js/modules/esnext.math.deg-per-rad";
import "core-js/modules/esnext.math.degrees";
import "core-js/modules/esnext.math.fscale";
import "core-js/modules/esnext.math.rad-per-deg";
import "core-js/modules/esnext.math.radians";
import "core-js/modules/esnext.math.scale";
useBuiltIns: ‘usage’

Automatically detect new features used in the code, and in combination with the target platform, determine which polyfills to introduce for the new feature, so this configuration is designed to minimize the number of polyfills to ensure the resulting Bundler size.

However, it is important to note that becausebabelWorking with code is inherently a time-consuming process, so in our actual projects it is usually the case thatnode_modulesIn the middle ofpackageforexcludeConfiguration to ignore, unless it is something that explicitly needs to go into the projectbabelCompilation ofpackageWill go aloneinclude, souseBuiltIns: 'usage'There’s a risk in this usagenode_modulesThese third party packages are not processed during the actual compilation and packaging process (e.gpackageESM specification provides source code, at the same timepackage.jsonIt’s also configuredmoduleField, then for example usewebpackSuch packaging tools will be introducedmoduleField corresponding entry file)

Also, if you use the useBuiltIns: ‘usage’ configuration. The associated polyfill is introduced into each file, so this would be redundant without Webpack.

useBuiltIns: false

Don’t add polyfills automatically per file, and don’t transform import “core-js” or import “@babel/polyfill” to individual polyfills.

corejs

CoreJS configuration options need to be used with either useBuiltIns: usage or useBuiltIns: entry. By default, the polyfills that are injected are stable features that have been incorporated into the ECMAScript specification. If you need to use any of the features in the Proposals, you need to configure them:

{"presets": [["@babel/preset-env", {// The presets are bound by CoreJS: {version: 3, Proposals: True}}]]}

@babel/plugin-transform-runtime

Background:

Babel uses a number of helper functions, such as _extend, as part of the compilation process. These helper functions are typically added to every file that needs to be processed.

So the @babel/plugin-transform-runtime problem is to direct all incoming helpers that need these helper functions to the @babel/runtime/helpers module, Instead of adding the content of the corresponding helper function to each file.

Another goal is to create a sandbox environment. Because if you import core-js directly, or @babel/polyfill, the polyfills it provides, such as promises, sets, maps, etc., are defined directly in the global context. This affects the contents of all files that use these APIs. So if you’re writing a library, it’s best to use @babel/plugin-transform-runtime to implement the polyfill to avoid contaminating the overall environment.

What this plug-in does is actually a referencecore-jsRelated modules to completepolyfillThe function. The final effect and use@babel/polyfillIt’s the same thing.

Configuration method:

{
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "corejs": 3
      }
    ]
  ]
}

The plugin defaults to assuming that all polyfillable APIs will be provided by the user. Otherwise the corejs option needs to be specified.

CoreJS: 2 only supports global definitions, such as Promise, and static methods, such as Array. From. Methods on instances, such as []. Includes, are not supported. CoreJS: 3 does, however, support methods on instances.

By default @babel/plugin-transform-runtime does not introduce the polyfills that are proposed by RFPs. If you are using coreJS: 3, you can enable this by setting proposal: true.

corejs option Install command
false npm install --save @babel/runtime
2 npm install --save @babel/runtime-corejs2
3 npm install --save @babel/runtime-corejs3

Technical implementation details

The transform-runtime transformer plugin does three things:

  1. Automatically requires @babel/runtime/regenerator when you use generators/async functions (toggleable with the regenerator option).
  2. Can use core-js for helpers if necessary instead of assuming it will be polyfilled by the user (toggleable with the corejs option)
  3. Automatically removes the inline Babel helpers and uses the module @babel/runtime/helpers instead (toggleable with the helpers option).

What does this actually mean though? Basically, you can use built-ins such as Promise, Set, Symbol, etc., as well use all the Babel features that require a polyfill seamlessly, without global pollution, making it extremely suitable for libraries.

Some tips

  1. If you are using@babel/preset-envuseBuiltIns: usagecollocationbrowserlistThis kind ofpolyfillIn a way that,polyfillIs polluting the overall situation (entryPatterns also pollute the global). However, this configuration will reduce the number of packages that do not need to be added to the compile packaging process to some extent depending on the target packaging platformpolyfillThis approach also corresponds to a reduction in the final size of the bundle.
  2. If it is go@babel/plugin-transform-runtimeThe plug-inpolyfillIt will not pollute the whole situation. But the plugin is not availablebrowserlistThe target platform configuration policy. So in your code as long as it is usedES6+The new API, will all introduce the correspondingpolyfillFile (regardless of whether the new API is already implemented by the target browser), which will also cause the bundle to grow in size. Officials have also tried to offer a new solution to the problembabel-polyfillsPackage, and policies to solve similar problems. See the correspondingThe documentAs well asissue

The related documents

  1. @babel/plugin-transform-runtime
  2. Polyfill or transform – runtime