What is the Babel

The official explanation is the compiler for the next generation of JavaScript syntax.

Since it is the standard of the next generation of Javascript, browsers will have compatibility problems due to different versions of Javascript, and the new methods of Javascript cannot be used. However, we have been advocating the use of the latest syntax sugar in project development, which can not only reduce the amount of code, Moreover async,await and other new features also solve the callback writing mechanism, reduce the code maintenance cost.

This is where Babel comes in. It lets you use most of JavaScript’s new standard methods and compile them into code that is compatible with most major browsers. In project scaffolding, a. Babelrc file is usually used, which is packed and compressed by configuring some parameters with WebPack. I also learned from the Internet that there are different writing methods and different parameters. Therefore, I reorganize a document and introduce the meaning of each configuration item in detail so that I can clearly understand how to use it.

The following configuration is mainly for Webpack3 +.

Babel translation unit

In the. Babelrc configuration file, presets and plugins are mainly configured. Therefore, different translators have different configuration items, which can be roughly divided into the following three items:

1. Syntax escapes. Compile javascript’s latest syntactic sugar, not translate new javascript apis and global objects. For example, let/const can be compiled, while includes/ object. assign cannot. The commonly used presets include babel-preset-env, babel-preset- ES2015, babel-preset- ES2016, babel-preset- ES2017, and babel-preset-latest. In actual development, just babel-Preset -env can be used instead of the rest, but it needs to be used with javascirpt production specification and is the official recommended

{
  "presets": ["env", {
      "modules": false}]."stage-2"
}
Copy the code

2. Patch escape. Responsible for translating new javascript apis and global objects, For example, babel-plugin-transform-Runtime compiles object. assign, and also introduces babel-polyfill to ensure browser compatibility. Object.assign will be compiled into the following code:

__WEBPACK_IMPORTED_MODULE_1_babel_runtime_core_js_object_assign___default()
Copy the code

3. JSX and flow, the class of translators used to translate JSX syntax and remove type declarations, which you will use when using Rect, is named babel-preset- React

Creating presets

NPM is used to install babel-preset-xx. For example, if NPM install babel-preset-stage-2 babel-preset-env –save-dev is installed, the following configurations are available.

{
  "presets": [["env", options],
    "stage-2"]}Copy the code
Stage 2 configuration

Babel provides the following escape packages, with the configuration items of the corresponding configuration file in parentheses

babel-preset-stage-0(stage-0) 
babel-preset-stage-1(stage-1) 
babel-preset-stage-2(stage-2) 
babel-preset-stage-3(stage-3)
Copy the code

In addition to all the functions of preset-stage-0, the transform-do-expressions and transform-function-bind plug-ins are added, and the preset is recommended. The same preset-stage-1 translator adds some additional features besides containing all the functions of preset-stage-2.

Options Configuration Introduction

The official recommendation is to use babel-preset-env instead of installing some of the plugin packages (ES2015 -arrow- Functions, ES2015 -block-scoped-functions, etc.).

More configuration can refer to the website https://babeljs.io/docs/plugins/preset-env/

{
    "targets": {
        "chrome": 52,
        "browsers": ["last 2 versions"."safari 7"]."node":"6.10"
    }
    "modules": false
}
Copy the code

Targets can build compatible browser versions. If browsers are set, Browsers override targets’ native browser restrictions.

Targets. Node Compiling the Node version

Modules is usually set to false because the CommonJS specification is supported by default, along with other configuration parameters: Systemjs umd “amd” | “” |” “|” commonjs systemjs I still don’t know what specification writing, amd and umd and commonjs is relatively familiar, here is a brief list of writing standards.

Amd code specification, which will be used in NG1, mainly for dependency injection:

define(['jquery'].function($) {// methodfunction myFunc() {}; // Expose public methodsreturn myFunc;
})
Copy the code

The CommonJS specification is one of the most respected in the Node environment:

var $ = require('jquery'); / / methodfunction myFunc() {}; Module.exports = myFunc; // exports of modules. {% codeblock %} > umD specification, compatible with AMD and commonJS specification, currently used in third party plug-in writing: {% codeblock %} (function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD
        define(['jquery'], factory);
    } else if (typeof exports === 'object'Module. Exports = factory(require() {// Node, CommonJS, etc. Module. Exports = factory(require()'jquery'));
    } else{// Browser global variable (root = window) root.returnexports = factory(root.jquery); } }(this,function($) {// methodfunction myFunc() {}; // Expose public methodsreturn myFunc;
}));
Copy the code

Plugins

The plug-in configuration items, like the default configuration items, need to be configured with the corresponding plug-in of Babel. You can choose to configure the plug-in to meet a single requirement. For example, we will have the following configuration in the early stage:

{
  "plugins": [
    "check-es2015-constants"."es2015-arrow-functions"."es2015-block-scoped-functions",
    // ...
  ]
}
Copy the code

However, these plug-ins are extremely difficult to maintain and write, and env was officially recommended to replace these single plugin functions and simplify the configuration as follows. Babel-preset -env:

{
  "presets": [
    "es2015"]}Copy the code

Here are two common plug-ins: babel-plugin-transform-Runtime and babel-plugin-syntax-dynamic-import.

The basic configuration code is as follows:

{
  "plugins": [
    "syntax-dynamic-import"["transform-runtime"]]}Copy the code

transform-runtime

The transform-Runtime plug-in was created to address this under-compiled global object or global object method, but it only converts the ES6 syntax, not the new API. If you need to switch to a new API, you can also avoid compatibility issues by using Babel-Polyfill.

Compile object. assign, configure and unconfigure the webpack compiled code fragment as follows:

// Code snippet not set: __webpack_require__("ez/6");
var aaa = 1;

function fna() {
  var dd = 33333;
  var cc = Object.assign({ key: 2 });
  var xx = String.prototype.repeat.call('b', 3);
  if ("foobar".String.prototype.includes("foo")) {
    var vv = 1;
  }

  return dd;
}
Copy the code
// Set the code snippet:  /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_babel_runtime_core_js_object_assign___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_babel_runtime_core_js_object_assign__); __webpack_require__("ez/6");
var aaa = 1;

function fna() {
  var dd = 33333;
  var cc = __WEBPACK_IMPORTED_MODULE_1_babel_runtime_core_js_object_assign___default()({ key: 2 });
  var xx = String.prototype.repeat.call('b', 3);
  if ("foobar".String.prototype.includes("foo")) {
    var vv = 1;
  }

  return dd;
}
Copy the code

The class definition class is compiled, with and without webPack compiled code snippets as follows:

// Code snippet not set:function _classCallCheck(instance, Constructor) { if(! (instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var Canvas = function Canvas(height, width) {
  _classCallCheck(this, Canvas);

  this.height = height;
  this.width = width;
};

var Canvas2 = function Canvas2(height, width) {
  _classCallCheck(this, Canvas2);

  this.height = height;
  this.width = width;
};
Copy the code
// Set the code snippet:  /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_babel_runtime_helpers_classCallCheck___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_babel_runtime_helpers_classCallCheck__); var Canvas =function Canvas(height, width) {
  __WEBPACK_IMPORTED_MODULE_0_babel_runtime_helpers_classCallCheck___default()(this, Canvas);

  this.height = height;
  this.width = width;
};

var Canvas2 = function Canvas2(height, width) {
  __WEBPACK_IMPORTED_MODULE_0_babel_runtime_helpers_classCallCheck___default()(this, Canvas2);

  this.height = height;
  this.width = width;
};
Copy the code

The same compiling effect is achieved for Generator functions. Currently, this function is not used in the project, and promise is generally used instead, and async await is used, so this function is not tested.

Officials say that promises will be compiled as well, but the actual test results don’t work

After the final test of Webpack packaging, the transform-Runtime configuration was introduced, and the js file size of the packaging entry was slightly increased, which did not reduce the file size as officially stated

Unconfigured final packaging effect:

Final packing effect after configuration:

Although the file size will increase, some compatibility problems will be solved. At the same time, using transform-Runtime can reduce the definition of internal global functions, which respects the modularity concept of WebPack from the structure. Therefore, it is recommended to use this plug-in.

syntax-dynamic-import

This plugin solves the problem of dynamically importing modules

function nDate() {
  import('moment').then(function(moment) {
    console.log(moment.default().format());
  }).catch(function(err) {
    console.log('Failed to load moment', err);
  });
}

nDate();
Copy the code

If “stage-2” is used in the. Babelrc configuration item, the plugin may not be used and dynamic module introduction is also supported.

Otherwise, the following error will be reported:

  • Module build failed: SyntaxError: ‘import’ and ‘export’ may only appear at the top level, or ‘import’ and ‘export’ may only appear at the top level.

  • Module build failed: SyntaxError: Unexpected token, expected {

Other Configuration Items

ignore

The main effect is that you can specify which code not to compile

{
  "ignore": ["./module/a.js"]}Copy the code

Let, object. assign, and class definitions are not compiled.

__webpack_require__("ez/6");
const aaa = 1;

function fna () {
  let dd = 33333
  let cc = Object.assign({key:2})
  let xx = String.prototype.repeat.call('b', 3)
  if ("foobar".String.prototype.includes("foo")) {
    let vv = 1
  }

  return dd
}

function fna2 () {
  return fna() + aaa + __WEBPACK_IMPORTED_MODULE_0__b__["a"/* default */] } class Canvas { constructor(height, width) { this.height = height; this.width = width; } } class Canvas2 { constructor(height, width) { this.height = height; this.width = width; }}Copy the code

minified

If you use babel-CLI to package the compiled files, this configuration item will work. However, most of the files are still packaged by third-party tools, such as Webpack, so this configuration parameter is generally not set. UglifyJsPlugin in the WebPack plug-in does the compression.

comments

No comments, Boolean types are generated in the generated file, which is also integrated with UglifyJsPlugin in the WebPack plug-in.

env

The basic configuration is as follows:

{
  "env": {
    // testIf BABEL_ENV is not set, NODE_ENV is used. If BABEL_ENV is not set, development is used by default"test": {
      "presets": ["env"."stage-2"], // Instanbul is a tool used to test transcoded code"plugins": ["istanbul"]}}}Copy the code

Let’s talk about compatibility

By default, Babel only converts new JavaScript syntax, not new apis. Global objects such as Iterator, Generator, Set, Maps, Promise, etc., and methods defined on global objects (such as Object.assign) are not transcoded. Refer to the definitions. Js file of the babel-plugin-transform-Runtime module for details.

There are still browser compatibility problems after Babel is compiled. Transform-runtime and babel-polyfill are generally used together. For the latter, only require is required in the project entry file.

Of course, lodash library can be used to replace the object. assign function, and PROMISE can be used to replace Q.js, etc. In this way, the dependency does not need to introduce the above plug-ins, which can be arranged according to the specific project

conclusion

The.babelrc configuration file is mainly composed of presets and plugins, which can be used together with Webpack to share common configurations in projects. All the above are summed up through learning. I hope to point out any mistakes.

The configuration used for VUE project development is as follows:

{
  "presets": [["env", {
      "modules": false}]."stage-2"], // No comments are generated in the generated file"comments": false."plugins": ["transform-runtime"."syntax-dynamic-import"]."env": {
    // testIf BABEL_ENV is not set, NODE_ENV is used. If BABEL_ENV is not set, development is used by default"test": {
      "presets": ["env"."stage-2"], // Instanbul is a tool used to test transcoded code"plugins": ["istanbul"]}}}Copy the code

The react project uses the following configuration:

{
  "presets": [["env", { "modules": false}]."stage-2"."react"]."plugins": ["transform-runtime"]."comments": false."env": {
    "test": {
      "presets": ["env"."stage-2"]."plugins": [ "istanbul"]}}}Copy the code

2018-11-18 Supplementary information about stage-x introduction

Stage-3 includes the following plug-ins:

The transform – async – to – the generator support async/await

Transform-exponentiation-operator supports power operator syntax sugar

Stage-2 includes all stage-3 plugins, plus the following plugins:

Syntax -trailing-function-commas supports trailing comma functions. Very small

Transform-object-reset-spread supports destruct assignment of objects

Stage-1 includes all stage-2 plugins, including the following plugins:

Transform-class-constructor-call supports class constructors

Transform-class-properties Supports the static property of class

Transform-decorators support es7’s decorator pattern, @, which is actually a useful feature and a nice syntactic candy for HOC

Transform-export-extensions Supports the export method

Stage-0 includes all stage-1 plug-ins, including the following plug-ins:

Transform-do-expressions supports writing if/else in JSX

Transform-function-bind supports the :: operator to switch contexts, similar to ES5’s bind

[2018-12-10] About babel-plugin-syntax-dynamic-import

Thanks to @Dango # 1 for asking the question. After testing, when using WebPack version 4.20.2 and above (other versions above 4 are not tested for now), this plug-in is not needed, and stage-2 configuration is not required. Import and dynamic import can also be supported.

function nDate() {
  import('moment').then(function(moment) {
    console.log(moment.default().format());
  }).catch(function(err) {
    console.log('Failed to load moment', err);
  });
}

nDate();
Copy the code