This article summarizes the tools used in the Babel community and how to configure them properly. If you want to read the conclusion, skip to the last section of the article.

Directory:

  • @babel/preset-env
    • introduce
    • targets
    • spec
    • loose
    • modules
    • debug
    • include
    • exclude
    • useBuiltIns
    • corejs
    • forceAllTransforms
    • configPath
    • ignoreBrowserslistConfig
    • shippedProposals
  • @babel/preset-stage-x(waste)
  • @babel/polyfill
    • introduce
    • Side effects
  • @babel/runtime
    • introduce
    • Usage scenarios
  • @babel/plugin-transform-runtime
    • introduce
    • Demo
  • babel-register
  • babel-node
  • A copy of the available configuration
    • Install the corresponding package
    • babel.config.js
  • reference
    • The use of Babel
    • Configuration information for Babel

@babel/preset-env

introduce

Babel-preset -env is a set of plug-ins that are officially out of use for preset-201x and preset-latst, and env can automatically process compatibility code according to configuration.

Documents: babeljs. IO/docs/en/bab…

targets

string | Array<string> | { [string]: string }, defaults to {}

Specify the generated code environment for your project.

It can be a string:

{
  "targets": "> 0.25%, not dead." "
}
Copy the code

Can also be objects:

{
  "targets": {
    "chrome": "58"."ie": "11"}}Copy the code

The default is {}

{
  "targets": {}}Copy the code

For the environment values, refer to the Browserslist project.

targets.esmodules

Boolean.

It can also be optimized for browsers that support ES Module. When this option is specified, the Browsers field is ignored. You can use this with to generate smaller script code.

Note: Browsers are ignored when specifying the esmodules option.

{
  "presets": [["@babel/preset-env",
      {
        "targets": {
          "esmodules": true}}]]}Copy the code

targets.node

String | | “current” true.

If you want to compile against the current version of Node, you can specify “node” : true or “node” : “current”, which is the same as “node” : process.versions. Node.

targets.safari

String | “tp”.

If you want to compile against the technical preview of Safari, you can specify “Safari” : “TP”.

targets.browsers(waste)

String | Array < string >.

Select the browser query using Browserslist (for example: last 2 versions, > 5%, Safari TP).

Note that the browsers results are overwritten by an explicit item in targets. (This feature has been tested and deprecated)

Note: This will be removed in later versions, rather than directly setting targets to a browserslist compatible query.

{
  "targets": {
    "browsers": {
        "chrome": "58"."ie": "11"}}}// Is equivalent to, but the latest version is no longer available
{
  "targets": {
    "chrome": "58"."ie": "11"}}Copy the code

spec

Boolean, default false.

Any plug-ins that support them in this default enable a more compliant, but possibly slower, transformation.

loose

Boolean, default false.

This default allows any of their plug-ins to enable the “loose” transformation.

modules

Systemjs umd “amd” | “” |” “|” commonjs “|” CJS “| |” auto “false, defaults to” auto “.

Enable ES6 module syntax conversion to other module types.

Setting this to false will not transform the module.

Also note that CJS is an alias for CommonJS.

debug

Boolean, default false.

Output the version information specified in the targets/plugins and plug-in data using console.log.

include

Array < string | RegExp >, the default [].

An always-contained array of plug-ins.

The following configuration is valid:

  • Babel plug-in.@babel/plugin-transform-spreadAnd unprefixedplugin-transform-spreadAre supported.
  • Built-in features, such ases6.map.es6.setOr,es6.object.assign.

You can specify the plug-in name completely or partially (or use RegExp).

Supported writing:

  • The full name (string) : “es6. Math. Sign.” “
  • Part (string): “es6.math.*” (parse to all bandses6.mathPrefix plugins)
  • Regular objects:/^transform-.*$/ornew RegExp("^transform-modules-.*")

Note that the. In the re object above means to match any character, not the actual. Characters. Also note that matches any character. .* is used in the re, unlike * in the glob format.

This option focuses on bugs in native enhancement code, or a set of unsupported features that do not work.

For example, Node 4 supports native classes but not spread. If super requires the spread feature, then the @babel/plugin-transform-classes plugin needs to be included.

Note: The include and exclude options only apply to plug-ins included in this preset; Therefore, including @babel/plugin-proposal-do-expressions exclusion or @babel/plugin-proposal-function-bind in the option throws an error (because this default does not have these items). To use a plug-in not included in this default, add it directly to the Plugin option.

exclude

Array < string | RegExp >, the default [].

An array of plugins that are always excluded/removed.

The configuration options are the same as include.

If you do not want to use generators and do not want to include regeneratorRuntime (when using useBuiltIns), or use another plugin (such as fast-Async) instead of Babel’s Async-to-Gen, This option disables transformations such as @babel/plugin-transform-regenerator.

useBuiltIns

“Usage” | | “entry” false, the default is false.

This option references the core-JS module directly as a bare import. Therefore, core-js will parse relative to the file itself and will be accessible. If there are no core-JS dependencies or multiple versions, you may need to specify core-js@2 as a top-level dependency in your application.

This option configures how @babel/preset-env handles polyfills.

useBuiltIns: 'entry'

Note: just use require(“@babel/polyfill”) throughout your app; At a time. Multiple imports of @babel/polyfill can lead to global collisions and other hard-to-track errors. We recommend creating a separate file to handle the REQUIRE statement.

This option will enable a new plug-in that replaces the import “@babel/polyfill” or require(“@babel/polyfill”) with separate items imported under @babel/polyfill based on different environments.

npm install @babel/polyfill --save
Copy the code

The input

import "@babel/polyfill";
Copy the code

Output (varies according to configuration environment)

import "core-js/modules/es7.string.pad-start";
import "core-js/modules/es7.string.pad-end";
Copy the code

You can also import core-js directly (import “core-js”; Or the require (‘ core – js);)

useBuiltIns: 'usage'(Experimental)

As polyfill is used in each file, specific imports are added for polyfill. We use Bundler to load the same Polyfill only once.

The input

a.js

var a = new Promise(a);Copy the code

b.js

var b = new Map(a);Copy the code

Output (if the current configured environment does not support this feature)

import "core-js/modules/es6.promise";
var a = new Promise(a);Copy the code
import "core-js/modules/es6.map";
var b = new Map(a);Copy the code

Output (if the current configured environment supports this feature)

var a = new Promise(a);Copy the code
var b = new Map(a);Copy the code

useBuiltIns: false

Neither polyfills are automatically added to each file, nor “@babel/polyfill” is imported as a single polyfill.

Simple summary

Difference between ‘usage’ and ‘entry’ :

  • 'usage'No need to introduce in the headerimport '@babel/polyfill', it automatically introduces the corresponding feature based on the current code and only references itIn the codeFeatures (browserslist configuration + code used)
  • 'entry'It needs to be introduced in the head'@babel/polyfill'And the corresponding features are introduced according to the configuration environment. It’s not used in the code, but it’s missing in the environment, it’s introduced. (Only configured according to Browserslist)

Since we usually use the dependencies package of NPM for business development, Babel does not detect the dependencies package code by default. That is, if a dependency uses Array.from but its own business code doesn’t use the API, the polyfill built doesn’t have array. from, which can cause bugs for users of older browsers. To avoid this, open source third-party libraries are usually converted to ES5 when they are released.

corejs

The Corejs configuration item is used to determine the current version of Babel and has options 2 and 3.

As explained in the update documentation, the latest babel7@babel /polyfill removes polyfill proposals, so @babel/ Polyfill is just an alias for Core-JS V2.

Corejs: 2 + useBuiltIns: ‘Entry’ will give you a warning:

`@babel/polyfill` is deprecated. Please, use required parts of `core-js` and `regenerator-runtime/runtime` separately
Copy the code

Corejs: 3 + useBuiltIns: ‘Entry’ is used to avoid errors.

forceAllTransforms

Boolean, default false.

Thanks to the support of Babel7 Javascipt Config file, you can control the transformation depending on whether production is set.

module.exports = function(api) {
  return {
    presets: [["@babel/preset-env",
        {
          targets: {
            chrome: 59.edge: 13.firefox: 50,},// for uglifyjs...
          forceAllTransforms: api.env("production"),},],],}; };Copy the code

Note: Targets. Uglify has been deprecated and will be removed in the next version.

By default, this default will run all transformations required by the target environment. If you want to force all transformations to run, enabling this option can be useful in some scenarios where UglifyJS is required or only ES5 syntax is supported.

configPath

String, default is process.cwd()

Decide to configure the starting point of browserslist search up to the system root directory until it is found.

ignoreBrowserslistConfig

Boolean, the default is false

Toggle whether to use Browserslist to configure sources, including searching for any Browserslist files or referencing the Browserslist key in package.json. This is useful for projects that do not compile with Babel, but are configured using Browserslist.

shippedProposals

Boolean, the default is false

Toggle to enable support for built-in features provided in the browser. If your target environment has native support for a feature proposal, the parser syntax plug-in that matches it will be enabled rather than performing any transformations. Note that this does not enable the same transformation as @babel/preset-stage-3, as these proposals may change before the official landing browser.

Currently, the following contents are supported:

Built-in:

  • es7.array.flat-map

Features:

  • There is no

@babel/preset-stage-x(waste)

In Babel7, it was officially announced that the Babel Stage Preset pack was scrapped, presumably because the widely used Stage-x was not suitable for the community, see the official blog for reasons

In the new version of Babel configuration, you need to download the proposal plug-in according to your needs, because stage-x itself is a collection of these plug-ins, but is not included in the env package, such as installation: Babel /plugin-proposal-function-bind, using these language features that are not officially standard but are already widely used in the community.

In specific use, the previous stages are equivalent to the following collection of plug-ins:

{
  "plugins": [
    // Stage 0
    "@babel/plugin-proposal-function-bind".// Stage 1
    "@babel/plugin-proposal-export-default-from"."@babel/plugin-proposal-logical-assignment-operators"["@babel/plugin-proposal-optional-chaining", { "loose": false }],
    ["@babel/plugin-proposal-pipeline-operator", { "proposal": "minimal" }],
    ["@babel/plugin-proposal-nullish-coalescing-operator", { "loose": false}]."@babel/plugin-proposal-do-expressions".// Stage 2
    ["@babel/plugin-proposal-decorators", { "legacy": true}]."@babel/plugin-proposal-function-sent"."@babel/plugin-proposal-export-namespace-from"."@babel/plugin-proposal-numeric-separator"."@babel/plugin-proposal-throw-expressions".// Stage 3
    "@babel/plugin-syntax-dynamic-import"."@babel/plugin-syntax-import-meta"["@babel/plugin-proposal-class-properties", { "loose": false}]."@babel/plugin-proposal-json-strings"]}Copy the code

@babel/polyfill

introduce

Documents: babeljs. IO/docs/en/nex…

Official website information: Since Babel 7.4.0, this package has been deprecated, To support direct import of Core-js /stable (polyfill ECMAScript feature) and regenerator-Runtime/Runtime (need to use converted generator functions)

The purpose of babel-Polyfill is to “patch” the browser. For example, if the browser doesn’t have object. assign, it will create this feature for that environment. Babel itself just transforms the syntax and doesn’t add missing features, and Polyfill is there to make up for missing features in browsers (like some Ie).

Babel-polyfill is equivalent to regenerator Runtime + core-js.

  • Regenerator: Provides support for generators if generator and async functions are used in application code.
  • Core-js: Provides new es features.

For detailed usage of the latest version, see useBuiltIns feature of @babel/preset-env.

Through my simple experiments, it turns out that you don’t need to install this package, and the new Corejs V3 is not quite the same as Corejs V2 (confusingly). Just use useBuiltIns.

Side effects

The introduction of Babel-Polyfill also has some side effects, such as:

  • New global objects were introduced, such as Promise, WeakMap, etc.
  • Modify existing global objects: for example, modify the prototype chain of Array, String, etc.

In the application development, the above behavior is not a big problem, basically controllable. However, if babel-Polyfill is introduced into library and tool development, it presents potential problems.

For example, if you define a nonconforming array.from () function in a project and introduce a library that relies on babel-Polyfill, the library may override the custom array.from () function, causing an error.

That’s why Babel-Runtime exists. It extracts the global built-in objects that developers depend on into separate modules and introduces them through module import, avoiding the modification (pollution) of the global scope.

Therefore, if you are a development library or tool, you can consider using babel-Runtime.

@babel/runtime

introduce

Babel/Runtime is a library containing Babel Modular Runtime helpers and a series of Regenerator-Runtime modules.

Documents: babeljs. IO/docs/en/bab…

Usage scenarios

Babel-runtime is generally used in two scenarios:

  • Development libraries/tools
  • Remove redundant helper functions.

It differs from Babel-Polyfill in that:

  • Babel-polyfill modifies (overwrites) instance methods, which is useful in the business layer, but some scenarios, such as referring to external technical libraries, don’t want the polyfill here to overwrite methods in the business code.
  • Babel-runtime does not modify instance methods, it just introduces helper functions to create corresponding methods.

Use babel-runtime with babel-plugin-transform-runtime. Babel-plugin-transform-runtime is used for code conversion during the build process, and babel-Runtime is the functional module that actually imports the project code.

@babel/plugin-transform-runtime

introduce

Documents: babeljs. IO/docs/en/bab…

Babel inserts inline helpers code at the top of each required file, which can result in multiple files having duplicate helpers code. The @babel/ plugin-transform-Runtime helpers option allows these modules to be removed.

@babel/ plugin-transform-Runtime does three things: core-JS aliasing, Helper aliasing and egenerator aliasing.

  • Core-js aliasing: automatically import babel-Runtime /core-js and map global static methods, global built-in objects to corresponding modules.

  • Helper aliasing: Remove inline utility functions and import them through the babel-Runtime /helpers module, such as the _classCallCheck utility.

  • Regenerator aliasing: If you use async/generator, babel-Runtime/Regenerator will be imported automatically.

Demo

module.exports = {
    "plugins": [["@babel/plugin-transform-runtime",
            {
                "corejs": false.// Boolean or number (default false) specifies whether runtime corejs aliasing is needed, or false if env useBuiltIns + polyfill is used.
                "helpers": true.// Boolean, default true, specifies whether to inline Babel helper code (e.g. ClassCallCheck, extends)
                "regenerator": false.// Preset -env already uses the global regeneratorRuntime, and the transform-Runtime is no longer needed for the non-polluting global regeneratorRuntime
                "useESModules": true.// Boolean, default false, use es modules helpers to reduce commonJS syntax code
                "absoluteRuntime": false // Boolean, default false, whether directory references runtime package (some projects reference code outside the current project, runtime package will not be found when compiled)}}]]Copy the code

Add the compiled code before the new configuration

import "core-js/modules/es6.promise";
import "regenerator-runtime/runtime";

function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
Copy the code

Add the compiled code after the new configuration

import "core-js/modules/es6.promise";
import "regenerator-runtime/runtime";
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
Copy the code

babel-register

Babel-register provides dynamic compilation. In other words, our source code can actually run in production without Babel compilation.

Let’s start by installing babel-Register under the project:

$ npm install --save-dev @babel/register
Copy the code

Then require in the entry file:

require('@babel/register')
require('./app')
Copy the code

By introducing @babel/ Register in the header of the entry file, we can use any ES2015 feature in our app file.

The downside, of course, is dynamic compilation, resulting in a loss in speed and performance. So this item is rarely used in a formal production environment.

babel-node

As mentioned above, babel-Register provides dynamic compilation that allows our source code to actually run in production – but we still need to make some adjustments, such as adding an entry file and requiring (‘@babel/register’) in that file. Babel-node can actually do a line of source code without changing it:

$ npm install --save-dev @babel/core @babel/node
$ npx babel-node app.js
Copy the code

However, don’t use Babel-Node in a production environment, because it is dynamically compiled source code and applications start up very slowly.

A copy of the available configuration

Install the corresponding package

Rely on:

  • @babel/core(Core package)
  • @babel/preset-env(the default)
  • @babel/polyfill(V7.4.0 seems to be deprecated and can not be installed)
  • core-js(Latest version v3, in case of configuration version corejs:3, this package is used to replace polyfill)
  • @babel/runtime(Development of business code is basically only using helper configuration, development technology library can be used in depth)
  • @babel/plugin-transform-runtime(Merge duplicate helper functions)
  • @babel/plugin-proposal-function-bind(Without stage-x, a separate plug-in needs to be installed to support the corresponding proposal features)

Note: @babel/polyfill can be installed with or without it, and it doesn’t seem to affect it, but it’s not sure if it will report an error when it is officially allowed to run. Look at the source code, actually very simple, is to reference core-JS V2 features. The official documentation has been scrapped.

babel.config.js

const presets = [
    [
      "@babel/env",
      {
        targets: {
          edge: "17".firefox: "60".chrome: "67".safari: "11.1".ie: '8'
        },
        useBuiltIns: 'usage'.// Babel7 needs to specify the version to introduce corejs, preferably using 3
        corejs: 3.modules: 'amd'.// What module system do you want to convert to},]];const plugins = [
    // Help reduce helper functions
    [
      "@babel/plugin-transform-runtime",
      {
          "corejs": false.// The default value can be left blank
          "helpers": true.// By default, it can not be written
          "regenerator": false.// Preset -env already uses the global regeneratorRuntime, and the transform-Runtime is no longer needed for the non-polluting global regeneratorRuntime
          "useESModules": true.Use es Modules helpers to reduce commonJS syntactic code}].// Since stage-x is no longer available, the required plug-ins need to be imported separately
    [
        '@babel/plugin-proposal-function-bind']]module.exports = { presets, plugins };
Copy the code

reference

The use of Babel

  • Juejin. Cn/post / 684490…
  • Github.com/Weiyu-Chen/…
  • blog.zfanw.com/babel-js/
  • Juejin. Cn/post / 684490…

Configuration information for Babel

  • 2 ality.com/2015/12/bab…