Babel is a compiler. Like other compilers, the compilation process is divided into three stages, namely parsing, transforming and generating. The analysis and generation phase is completed by the Babel core, and the conversion phase is completed by the Babel plug-in. So if we want to implement code conversion, we need to add plugins for Babel. Babel also provides a lot of interfaces for us to write our own plug-ins to transform our actual code.
Introduction of the plug-in
The following is a typical Babel plug-in structure:
export default function({ types: babelTypes }) {
return {
visitor: {
Identifier(path, state) {},
ASTNodeTypeHere(path, state) {}
}
};
};
The contents we need to pay attention to are as follows:
- babelType: A tool set similar to lodash, which is mainly used to manipulate AST nodes, such as creating, verifying, and transforming. For example, to determine whether a node is an identifier.
- path: There are many nodes in the AST, each node may have different attributes, and there may be associations between the nodes. Path is an object, which represents the association between two nodes. We can access the attributes of the node on the path, or access the associated node through the path.
- state: represents the state of the plug-in, we can access the configuration items of the plug-in through state.
- visitor: Babel visits each node of the AST in a recursive manner. The reason it is called a visitor is just because there is a similar design pattern called the visitor pattern, so you don't need to care about the details behind it.
- Identifier, ASTNodeTypeHere: Each node of the AST has a corresponding node type, such as identifiers, function declarations, etc. You can declare attributes with the same name on the visitor. When Babel traverses to the corresponding type of node, the method corresponding to the attribute will be Call, the parameters passed in are path and state.
Use of plug-ins
For example, let's implement a simple plug-in that converts all identifiers named hello into xkd.
First, make sure that the @babel/cli dependency has been installed. If not, you can execute the following command:
npm install --save-dev @babel/cli
Then you can start to create a plug-in and determine whether the name of the identifier is a, and if it is, replace it with xkd. The content of the plugin.js file is as follows:
module.exports = function({ types: babelTypes }) {
return {
name: "simple-plugin-replace",
visitor: {
Identifier(path, state) {
if (path.node.name === 'a') {
path.node.name = 'xkd';
}
}
}
};
};
Then write the source code in the index.js file, for example:
var a = 10;
function func(){
var a = 20;
console.log(a);
}
Execute the following commands:
npx babel --plugins ./plugin.js index.js
The output transcoding result is:
"use strict";
var xkd = 10;
function func() {
var xkd = 20;
console.log(xkd);
}
As you can see, all the identifier a in the code has been replaced with xkd.
Plugin configuration
The plug-in can have its own configuration items. We can modify the previous example to see how to obtain configuration items in the Babel plugin.
Example:
For example, we modify the configuration items in the .babelrc file:
{
"plugins": [ ["./plugin", {
"a": "one",
"b": "two"
}] ]
}
Then modify the plug-in code to obtain the configuration parameters from state.opts.
module.exports = function({ types: babelTypes }) {
return {
name: "simple-plugin-replace",
visitor: {
Identifier(path, state) {
let name = path.node.name;
if (state.opts[name]) {
path.node.name = state.opts[name];
}
}
}
};
};
Write the required test code in the index.js file:
let a = 10;
let b = 20;
Run the transcoding command npx babel index.js, and the output after transcoding is as follows:
let one = 10;
let two = 20;
Translation plugin
There are two types of plug-ins: translation plug-ins and grammar plug-ins. Translation plug-ins can be used to translate codes. The same type of grammar may have both a grammar plug-in version and a translation plug-in version. If we use a translation plug-in, we don't need to use a grammar plug-in anymore, because the conversion plug-in will enable the corresponding grammar plug-in.
ES3
- member-expression-literals
- property-literals
- reserved-words
ES5
- property-mutators
ES2015
- arrow-functions
- block-scoped-functions
- block-scoping
- classes
- computed-properties
- destructuring
- duplicate-keys
- for-of
- function-name
- instanceof
- literals
- new-target
object-super
`- parameters
- shorthand-properties
- spread
- sticky-regex
- template-literals
- typeof-symbol
- unicode-escapes
- unicode-regex
ES2016
- exponentiation-operator
ES2017
- async-to-generator
ES2018
- async-generator-functions
- dotall-regex
- named-capturing-groups-regex
- object-rest-spread
- optional-catch-binding
- unicode-property-regex
Modules
- modules-amd
- modules-commonjs
- modules-systemjs
- modules-umd
Experimental
- class-properties
- decorators
- do-expressions
- export-default-from
- export-namespace-from
- function-bind
- function-sent
- logical-assignment-operators
- nullish-coalescing-operator
- numeric-separator
- optional-chaining
- partial-application
- pipeline-operator
- private-methods
- throw-expressions
- private-property-in-object
Grammar plugin
After we add the grammar plugin, the parsing step enables Babel to parse specific types of grammar.
Or you can provide any plug-in options from the Babel parser. For example, the .babelrc file can be configured as follows:
{
"parserOpts": {
"plugins": ["jsx", "flow"]
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。