Babel Getting Started Guide

Babel js Guide -Part 1- The Absolute Must-Know Basics: Plugins, Presets, And Config

This article will cover:

  • What is Babel and how to use it in daily development?
  • What are presets and plugins and their differences? What is their execution order in babel execution?

Although the title of the original text seems to be a series, the author doesn't seem to continue, but I have figured out what to write in the next part; Non professional translation, with their own understanding, with small changes.

What is Babel

babel Is a free and open source JavaScript compilation library It converts the code into various JS codes according to your configuration.

The most common way to use it is to convert the code written by modern syntax JavaScript es6 + into es5, so as to be compatible with more browsers (especially IE). Take Babel's conversion of es6 arrow function into es5 function as an example.

// The original code
const foo = () => console.log('hello world!');

After transfer

// The code after babel transpilation
var foo = function foo() {
  return console.log('hello world!');
};

You can be here Try online

Using Babel

Online Repl

This is the easiest way to use Babel. This may not be a very practical tool, but it is the fastest tool to test or experiment with how Babel works, Online Repl address.

Build library

The most popular way to use Babel is to use construction libraries such as Webpack, Gulp or Rollup. Each approach uses Babel as part of the build to implement its own build process.

For example, our most commonly used webpack:

{
  ...
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            plugins: ['@babel/plugin-transform-arrow-functions']
          }
        }
      }
    ]
  },
  ...
}

Common building tool for Library: Rollup

rollup.rollup({
  ...,
  plugins: [
    ...,
    babel({
      plugins: ['@babel/plugin-transform-arrow-functions']
    }),
    ...
  ],
  ...
}).then(...)

Scaffold cli

In addition to relying on the construction library, you can also directly use the command line to rely on the official @ babel/cli package to compile the code of NIIT:

# install the core of babel and it's cli interface
npm install @babel/core @babel/cli

# use the babel command line
babel script.js --out-file script-compiled.js

Babel Plugins

Babel is configured through plug-ins. Out of the box, Babel won't change your code. Without plug-ins, it is basically like this:

// Parse - > generate, vernacular is English to Chinese, Chinese to English
const babel = code => code;

Run the code through Babel plug-in, and your code will be converted into new code, as shown below:

// Parse - > do something - > generate, vernacular is to turn English into Chinese, add oil and vinegar, and turn Chinese into English
const babel = code => babelPlugin2(babelPlugin1(code));

Babel Presets

You can add a separate list of Babel plug-ins, but it is usually more convenient to use Babel presets.

Babel presets combines a collection of plug-ins. The options passed to presets will affect their aggregated plug-ins. These options will control which plug-ins are used and the configuration of these plug-ins.

For example, the @ babelplugin transform arrow functions plug-in we saw earlier is part of @ Babel / preset env presets.

@Babel / preset env may be the most popular presets. It converts modern JavaScript (i.e. ES Next) to older versions of JavaScript according to the preset configuration passed by the user (such as browsers: target browser / environment).

For example, it can convert () = > arrowfunctions, {... Deconstructing} and class {} into JavaScript syntax supported by older browsers, for example 🌰, The target browser is IE11:

// New grammar
class SomeClass {
  constructor(config){
    this.someFunction = params => {
      console.log('hello world!', {...config, ...params});
    }
  }
  someMethod(methodParams){
    this.someFunction(methodParams);
  }
  someOtherMethod(){
    console.log('hello some other world');
  }
}

After compilation:

// explained here: https://www.w3schools.com/js/js_strict.asp
"use strict";
// this is a babel helper function injected by babel to mimic a {...destructuring} syntax
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
// this is a babel helper function injected by babel for a faster-than-native property defining on an object
// very advanced info can be found here:
// https://github.com/babel/babel/blob/3aaafae053fa75febb3aa45d45b6f00646e30ba4/packages/babel-helpers/src/helpers.js#L348
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

// this is a babel helper function that makes sure a class is called with the "new" keyword like "new SomeClass({})" and not like "SomeClass({})"
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

// like "_defineProperty" above, but for multiple props
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

// used by babel to create a class with class functions 
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

var SomeClass =
/*#__PURE__*/ // this marks the function as pure. check https://webpack.js.org/guides/tree-shaking/ for more info.
function () {
  // the class got converted to a function
  function SomeClass(config) {
    // make sure a class is called with the "new" keyword
    _classCallCheck(this, SomeClass);
    // someFunction is set on SomeClass 
    this.someFunction = function (params) {   
      // notice how the {...config, ...params} became _objectSpread({}, config, params) here
      console.log('hello world!', _objectSpread({}, config, params));
    };
  }
  // this function adds the class methods to the transpiled class created above
  _createClass(SomeClass, [
    {
      key: "someMethod",
      value: function someMethod(methodParams) {
        this.someFunction(methodParams);
      }
    },
    {
      key: "someOtherMethod",
      value: function someOtherMethod() {
        console.log('hello some other world');
      }
    }
  ]);
  return SomeClass;
}();

For more complex build requirements, the configuration will use Babel. In the project root directory config. JS file. Because it is a JavaScript file, it is better than babelrc is more flexible. For example:

module.exports = function (api) {
  
  // Only execute this file once and cache the resulted config object below for the next babel uses.
  // more info about the babel config caching can be found here: https://babeljs.io/docs/en/config-files#apicache
  api.cache.using(() => process.env.NODE_ENV === "development")
  return {
    presets: [
      // Use the preset-env babel plugins
      '@babel/preset-env'
    ],
    plugins: [
      // Besides the presets, use this plugin
      '@babel/plugin-proposal-class-properties'
    ]
  }
}

@Different configurations of Babel / preset env may lead to different compiled codes. For example, when the configuration is latest 10 Chrome versions, the compilation result of the above code is the same as that before compilation. Because the above features are supported by chrome; However, if you adjust 10 to 30 and 40, you will find that more and more code will be compiled; You can click here Try it:

to configure

Babel Plugins and Presets is a very important concept. Babel configuration is composed of Plugins and Presets (several other advanced attributes can also be used);

The configuration is simple and can be used directly Babelrc, babelrc is a JSON5 file (like JSON, but it allows comments), which is placed in the project root directory, such as the following:

// Comments are allowed as opposed to regular JSON files
{
  presets: [
    // Use the preset-env babel plugins
    '@babel/preset-env'
  ],
  plugins: [
    // Besides the presets, use this plugin
    '@babel/plugin-proposal-class-properties'
  ]
}

For more complex configurations, generally use Babel config. js file instead babelrc file, because it is a js file, so it is better than babelrc configuration is more flexible. For example:

module.exports = function (api) {
  // Only execute this file once and cache the resulted config object below for the next babel uses.
  // more info about the babel config caching can be found here: https://babeljs.io/docs/en/config-files#apicache
  api.cache.using(() => process.env.NODE_ENV === "development")
  return {
    presets: [
      // Use the preset-env babel plugins
      '@babel/preset-env'
    ],
    plugins: [
      // Besides the presets, use this plugin
      '@babel/plugin-proposal-class-properties'
    ]
  }
  
}

Some configuration files can be very complex, such as the configuration of the Babel project itself babel.config.js . Don't panic! After reading this guide series, you will know the meaning of each line of this complex configuration (see, there is a cow flying in the sky).

Babel Plugins and Presets execution sequence

If you mix Plugins and Presets in your configuration, Babel will apply them in the following order:

  • First, apply plug-ins from top to bottom;
  • Then, apply the preset after the plug-in, from bottom to top;

For example 🌰:

{
  presets: [
    '@babel/preset-5', //   ↑    ** End Here ** Last preset to apply it's plugins *after* all the plugins below finished to run 
    '@babel/preset-4', //   ↑
    '@babel/preset-3', //   ↑    2
    '@babel/preset-2', //   ↑
    '@babel/preset-1', //   ↑    First preset to apply it's plugins *after* all the plugins below finished to run 
  ],
  plugins: [
    '@babel/plugin-1', //   ↓    >>> Start Here <<< First plugin to transpile the code.
    '@babel/plugin-2', //   ↓  
    '@babel/plugin-3', //   ↓    1
    '@babel/plugin-4', //   ↓  
    '@babel/plugin-5', //   ↓    Last plugin to transpile the code before the preset plugins are applied
  ]
}

In addition, it is worth mentioning that the plug-ins in each preset are also applied from top to bottom.

It is very important to configure Plugins and Presets in the correct order! The correct order may speed up the translation, and the wrong order may produce unwanted results or lead to errors.

Maybe it's above 🌰 If it's not real enough, let's have a real one:

{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react",
  ],
  "plugins": [
    ["@babel/plugin-proposal-decorators", { "legacy": true }],
  ]
}

Decorators is the decorator syntax, which is still in stage-3, and JSX is the exclusive syntax of React; If you don't compile @ Babel / plugin proposed decorators and @ Babel / preset React first and run @ Babel / preset env compilation directly, you will report @ or < div > invalid syntax ID. how important it is to configure plug-ins and plug-in order correctly.

Babel Plugins and Presets options

As mentioned above, setting different browsers options for @ Babel / preset env will get different compilation results; By wrapping the options in the array and adding options to it, you can pass the option configuration to Babel Plugins and Presets. For example, the object behind @ Babel / preset env is an option configuration, telling that the compilation target is compatible with chrome 58 and IE11:

{
  presets: [
    // Notice how @babel/preset-env is wrapped in an array with an options object
    ['@babel/preset-env', {
      "targets": {
        "chrome": "58",
        "ie": "11"
      }
    }],
    '@babel/some-other-preset'
  ]
}

@Babel / preset env is basically a required preset for project compilation. In addition to targets, there are common options such as useBuiltIns, esmodules, modules, and more about configuration Reference official website

last

There are so many guidelines. We will launch an advanced chapter on Babel runtime and Babel Polyfill in the near future.

Tags: Javascript Front-end Babel

Posted by d3ad1ysp0rk on Sun, 22 May 2022 11:11:57 +0300