I. About BABEL
babel
is the es6+ syntax compiler, official website: Www.babeljs.io, used to convert the old version of the browser unrecognized syntax and features into ES5 syntax, so that the code can apply more environment.
The initial babel
use is very convenient, almost only with a small number of configurations can be used, but with the rapid upgrading of tools and code architecture, babel
has been fission into a very many parts, each part of their own, The benefit of this is that the development environment can be scaled down by reducing the size of the formal package in the production environment (because it can be referenced on demand), but the disadvantage is that it is very expensive to use with developers who are unfamiliar with the software architecture because of the need to introduce more fragmented plug-ins in the development phase.
For example, the babel
official website in the webpack
configuration section, mentioned babe-loader
, babel-core
and babel-preset-env
three plug-ins, and when the developer in the webpack
actual configuration in addition to the above three basic plug-ins, will encounter babel-polyfill
, and babel-runtime
babel-plugin-transform-runtime
so on a series of plug-ins, Perhaps by looking at the plugin's instructions to understand the functionality of the plugin, it is difficult for developers to determine whether they should use this feature or when to use it.
Two. Basic demand deduction
From the point of view of tool design, we look at the changes by the way of problem deduction babel
.
In the ES6
standard launch, the browser is not well supported, but ES6
a lot of features and syntax is very attractive, so people think of a way, that is, to ES6
write code, and then out of the package to take a tool to convert it into a more browser to recognize the ES5
syntax is not OK, so , the Babel
basic model appears:
babel
function is defined as a compilation tool, it is theoretically possible to use the compiler's generic code framework, with Astparser------traverse--- stringify steps to implement the compile function, in a key traverse session, A set of rules is required, but the standard of transcoding is ES6
not a standard for finalization, and each of these features needs to be formally finalized in 5 stages, from stage0 to stage4 , only stage-2 the above-mentioned features of the draft (draft) phase will be supported in the future, while the criteria below this stage are likely to be discarded, and if all conversions are made, it will not only reduce the efficiency of the tool, but will also cause pitfalls for future maintenance of the code.
So if we have a factory function that takes the number 0-4 as a parameter and then returns all of the rule sets that went through the stage-x (a ES6
subset of the rules) as a rule set, you can reduce the code volume when you eventually generate the code for your production environment, if you babel_get_es6_by_stage(2)
Such a function returns the ruleset, so the implementation code for stage-0 and stage-1 is not required in the formal code. Based on the above considerations, we Babel
perform the first function stripping of the tool:
Deduction continues, after a volume reduction of the ruleset, we get a relatively thin set of rules, which contains many new syntax and methods, if used directly that is really cool, after all, the introduction of a tool can have no worries about the use of new features, but for the production environment of the Code package, The code redundancy caused by this practice is very difficult to accept.
In bootstrap
the case of everyone familiar with bootstrap.min.css
it, the volume is about 120k
, but you will find that many people introduce it entirely out of the mind inertia, and in the end only use very basic btn
related style classes, or just to use the col-md-4
style of this responsive layout, All the styles used may take up only 20k-30k space, but they have to introduce a 120k library for the project, and not all projects will care about the difference between 20k and 120k.
Then we need a method that can be combined in a smaller granularity babel_get_es6_by_rules([rule , ...])
, allowing the user to choose the syntax and method they use to reduce the size of the reference library:
The deduction continues. Developers dealing with compatibility issues know that browsers are version-differentiated, many features are implemented and behave differently in different browsers, and for ES6
this, ES6
some of the features in the newer browsers have been implemented incrementally, If the operating environment used by our target users ES6
has already provided native support for some features, or if the target user's operating environment is simply encapsulated by the developer, there will be a lot of unnecessary parts in the original "Yiguoduan" Transcoding method.
For example, if you choose to transcode a keyword to define a class in a rule set, Babel will need to transcode Class
it to be used function
and prototype
ES5, but if your target users are all programmers, Almost all using a high version of Chrome as the project environment, the above transcoding may be superfluous.
To sum up, we need to provide a way for Babel to determine whether the target environment needs transcoding, babel_get_rule_as_need( rule_set , env_info)
passing the first filtered rule set and the target user's environment information into the method, the rule set is again streamlined, then we need to optimize the Babel again:
At babel
this point, you have the ability to do the necessary transcoding for different use environments, but this is not the whole problem, ES6
new features in addition to the syntax of the update, but also added a lot of native methods or types, such as, such as such Map
Set
Promise
new Global objects, or Array.from
This kind of static method, and so on, syntax escaping does not complete the recognition of these features, because both in the ES5 environment or the ES6 environment you write this, only when the browser will be running, you can tell you that an object or a method does not exist.
For example, the following code:
function addAll() { return Array.from(arguments).reduce((a, b) => a + b);}
When escaped, it becomes:
function addAll() { return Array.from(arguments).reduce(function(a, b) { return a + b; });}
However, it is still not available anywhere because it is not supported by all JAVASCRIPT environments Array.from
. For this class of non-grammatical features, we want to be able to provide support automatically in the tool, which has a proprietary title called "Polyfill"(or "shim").
We can either proactively provide an array of shim inserts that need to be added, or you can use a passive way to put an array of this type of new feature encountered in the transcoding process, API
by installing the appropriate shims for the Polyfill, it is important to babel_add_polyfill ( polyfill_list )
note that Polyfill is equivalent to extending the functionality of the browser, which takes precedence over the project business logic code, then the Babel logical framework becomes:
Deduction continues. In the above logical structure, we simply add the Polyfill library to the global variable, and the global variable is most likely to be rewritten to fail or conflict with other third-party libraries. So if you don't add Polyfill to the global, you need to split it into a separate module with equivalent functionality, and call it in a similar lodash
way or another underscore
, and we'll split the logical structure again:
At this point, we have completed the Babel toolset basic functions of the * Logical layer Division *, through the legend of the multi-back less complement (that is, the grammar ahead of the fallback, the method is not enough to hit the patch) way to achieve code compilation.
Three. Module partitioning
Based on the division result of the above business logic layer, we need to divide the code layer of the Babel tool into modules:
Four. The real Babel
If you can understand the above requirements deduction and Module Division, then congratulations you have mastered the basic structure of the Babel, we will be the original module diagram of the information to replace the actual name or plug-in, and some component division, you can see the basic structure of the real babel
toolset:
Of course, the real babel
function is much more than that, it provides interfaces for various environments, editors and automation tools, and also opens the plug-in development API
to the developers, interested readers can continue to understand deeply.
Five. Using Babel
babel
More than 8.0 of the version to move many plugins into the official warehouse, the installation method has changed, such as the babel-preset-env
address changed @babel/preset-env
, please refer babel
to the official website for configuration.
1.babel-cli
To facilitate the ability to use Babel directly at the command line, yarn global add babel-cli
add the following script to Package.json by babel-cli the command-line tool in the global installation:
"scripts":{ "babel":"babel main.js -o maines5.js"}
It can then be yarn run babel
compiled by using Babel at the command line, but looking at the compiled code will reveal that the files before and after the compilation are the same, because we did not specify any transcoding rules for them, and running Babel just traversed the resulting AST. If you want Babel to be able to implement transcoding, continue looking down.
2.babel-preset-env
Provides transcoding rules, a babel
combination of several plugins used in its lower version. In babel-preset-env
fact, the "all rules rule set + get_rules () method Set"that we describe in the problem deduction, you will node_modules
find many babel-plugin-transform-***
of these named packages in the folder, they are the rule sets, you can either set the preset
property, or you can refer to it by plugins
selecting the required transcoding rule in the attribute.
babel-preset-env
after installation, create a new file in the project folder .babelrc
and add the following configuration:
{ "presets":["env"], "plugins": []}
Or customize the escape rules that you need to support:
{ "presets":[], "plugins": [ "babel-plugin-transform-es2015-arrow-functions"//箭头函数转换规则 ]}
Running again babel
, you can see that the code you have written has been converted.
Before conversion:
//Arrow Function Array.from methodArray.from([1, 2, 3]).map((i) => { return i * i;});
After conversion:
"use strict";//Arrow Function Array.from methodArray.from([1, 2, 3]).map(function (i) { return i * i;});
Of course, you can also specify the target browser to remove unnecessary transcoding, for example, to .babelrc
specify a higher version of Chrome for the browser to match:
//.babelrc{ "presets":[ ["env", { "targets": { "browsers": "chrome 56" } }] ], "plugins":[]}
You can find that the arrow functions in the compiled script file still exist, indicating that this version of the chrome
browser has support for the arrow function, there is no need to escape.
The new version of Babel has been planned to support setting parameters in Package.json browserslist
To specify the usage environment that needs to be adapted, which means that the same set of configurations for the usage environment is stripped out and postcss
used for babel
autoprefixer
shared use by tools.
3.babel-polyfill
Babel is only responsible for syntax conversions, such as converting ES6 's syntax to ES5. But if there are objects or methods that the browser itself does not support, such as:
- Global objects: Promise, Weakmap, and so on.
- Global static functions: Array.from, Object.assign, and so on.
- Example methods: such as Array.prototype.includes.
At this point, you need to introduce a babel-polyfill
simulation to implement these objects, methods.
If the above compiled code is opened in the IE10
browser, you will see the browser does not support the Array.from method error, if the generated code needs to IE10
run in, then we need to introduce a compatible patch library, so that IE10
the browser environment can support this method.
babel-polyfill
It needs to be introduced in such a way that it can be incorporated into the script using the packaging tool:
//ES Moduleimport 'babel-polyfill'//或 CommonJsrequire ('babel-polyfill')
When you do this, you will find that it does solve the problem of error, but it is hard to accept that packaging will introduce the whole babel-polyfill
, and the packaged code adds nearly 4000 lines (about 400k volume increments). Can this plug-in babel-preset-env
be like the same as on-demand reference? Must be able to. babel-polyfill
is based on core-js
and regenerator
built, and only needs to be indicated at the time of reference, for example:
import 'core-js/modules/es6.array.from';//Arrow Function Array.from methodArray.from([1, 2, 3]).map((i) => { return i * i;});
When you package it, you'll find that the bundle file size is much smaller.
babel-polyfill
Implementation, as mentioned in the problem deduction, is polluting the global environment, and you may already realize that this tool, either simply configured after a surge in code, or on-demand reference configuration cumbersome. It is not recommended unless there is a requirement for low-version IE in medium-sized projects.
4.babel-runtime/babel-plugin-transform-runtime
If a thing is difficult to use, then soon there will be a substitute, the software of the world is such babel-runtime
a substitute. Extract the explanations in the blog post recommended below:
Babel-polyfill
Simple and rude, he will pollute the global environment, for example, in a browser that does not support promise Polyfill a global promise object for invocation, and an unsupported instance method adds a method to Polyfill on the corresponding constructor prototype chain.
Babel-runtime
Does not pollute the global environment, it will be polyfill locally, and will not convert some instance methods , such as ' abc '. Includes (' A '), where the includes method is not translated. It is generally combined babel-plugin-transform-runtime
to use.
In short, other features, in addition to the instance method, babel-runtime
will help you fix the patch. Add it directly to the configuration item when you use it plugins
babel-plugin-transform-runtime
.
In General, babel-polyfill
and babel-plugin-transform-runtime
all have their own use of the scene, but also can be used in combination with the actual project needs to be screened and introduced .
Six. Information recommendation
"Webpack+babel project in IE report promise undefined error leads to thinking"
It detailed explanation babel-runtime
of the babel-plugin-transform-runtime
related issues.
"How to write good. BABELRC?"
It detailed explanation of the various configuration items and optional parameters of the meaning, very practical.
Starter Guide: Babel-handbook
A great starter guide that explains the concepts and usage in Babel, and suggests a priority reading to help developers understand the Babel modules that are not covered in this article.
Official website: Www.babeljs.io
Many developers like to watch the tutorial but easy to ignore the official website, which is very strange. The official website will link to very good github warehouses, including not only the underlying modules in the Babel package, but also the Web sites that help us understand the guiding repositories and even ES2015 the main features, which are the main resources for learning Babel.