Develop a Babel plug-in
This article is a VsCode editor for the tutorial, if your editor is not VsCode then this article debugging methods you will not be able to use.
** What does this plugin do? **
- This is a plugin that automatically adds properties to React components.
** 2, if we achieve the effect? **
- 1. Add properties to React components
- 2. Can debug code using VsCode breakpoints
- 3, can use the shortcut command automatically package TS
Note: I didn’t write the code in babel-project/index.ts, it’s the code for babel-plugin-react-auto-props. The purpose of this article is to show you how to use VSCode for development and debugging, and to open the door to Babel plug-in development. The entire project directory structure:
.vscode
--launch.json // vscode debugs configuration files
--task.json // Automatically package the configuration
babel-project
--index.ts // Project code
dist // Project packaged file
--index.js
--index.js.map
lib // The converted code for our plug-in
--index.js
node_modules
test // Test the directory
--index.js
babel.config.js // Babel configuration file
package.json
package-lock.json
tsconfig.json // ts configuration file
Copy the code
Packages that need to be used (some packages are not used, just know) :
@babel/cli
@babel/preset-react
@babel/core
@babel/generator
@babel/template
@babel/traverse
@babel/traverse
@babel/traverse
@babel/types
babylon
@babel/preset-env
Step 1 (Create a directory)
- Start by creating a new directory
npm init
After init, create these subdirectories in this directory
.vscode
--launch.json
--task.json
babel-project
--index.ts
test
--index.js
Copy the code
- Then NPM I * * -d above the last package
Part 2 (Configuration Files)
tsconfig.json
We need to configure typescript with rootDir, outDir, what module type do we need to package target code into, etc.
{
"compilerOptions": {
"baseUrl": "."."paths": { "*": ["types/*"]},"module": "commonjs"."target": "es6"."outDir": "./dist"."lib": ["es6"."dom"]."sourceMap": true."rootDir": "babel-project"
},
"include": [
"babel-project/**/*"]."exclude": ["node_modules"]}Copy the code
.vscode/launch.json
This is the VsCode configuration file. We point the program parameter to babel-cli’s index.js and add the parameter setting entry and exit
{
"version": "0.2.0"."configurations": [{"type": "node"."request": "launch"."name": "Start program"."sourceMaps": true."program": "${workspaceFolder}/node_modules/@babel/cli/lib/babel/index.js"."args": [
"test/index.js"."-o"."lib/index.js"]]}}Copy the code
.vscode/task.json
This is the build command configuration file for VsCode. With this configured we can package our project code using shortcut keys
{
"version": "0.1.0 from"."command": "tsc"."isShellCommand": true."args": ["-p"."."."-w"]."showOutput": "always"."problemMatcher": "$tsc"
}
Copy the code
babel.config.js
This is our plug-in configuration file. If someone uses this plug-in in the future, this is what they’re going to configure
const presets = ['@babel/preset-react']
const plugins = [
[
'./dist/index.js',
{
"Button": {
"size": "small"}}]]module.exports = { presets, plugins }
Copy the code
package.json
Project dependency file configuration, this needless to say
. "scripts": { "build": "tsc" }, .....Copy the code
The test code
This is the code we will use to test the plug-in, and we will package this code as we want
let b = <PPP>1234</PPP>
let element = <Button color="red" />
Copy the code
babel-project/index.ts
Here comes the ontology ~ this is all the code for our plug-in.
// import * as babelCore from '@babel/core'
import * as parser from '@babel/parser'
import * as types from '@babel/types'
import traverse, { NodePath } from '@babel/traverse'
export default function() {
return {
visitor: {
CallExpression(path: NodePath<types.CallExpression>, state) {
// return if is not React call createElement expression
let { callee } = path.node
let b = 3;
if (
!(
types.isMemberExpression(callee) &&
types.isIdentifier(callee.object) &&
callee.object.name === 'React' &&
types.isIdentifier(callee.property) &&
callee.property.name === 'createElement')) {return
}
// get the component type name and it's extra props options
let [element, propsExpression] = path.node.arguments
let elementType: string
if (types.isStringLiteral(element)) {
elementType = element.value
} else if (types.isIdentifier(element)) {
elementType = element.name
}
const options: Object = state.opts
let extraProps: Object | undefined = options[elementType]
if(! extraProps) {return
}
// build the extra props ObjectExpression
let stringLiteral = JSON.stringify(extraProps)
let extraPropsExpression = parser.parseExpression(stringLiteral)
// if the default props is null(empty)
if (types.isNullLiteral(propsExpression)) {
path.node.arguments[1] = extraPropsExpression
} else if (types.isObjectExpression(propsExpression)) {
path.node.arguments[1] = types.objectExpression(
propsExpression.properties.concat(
(<types.ObjectExpression>extraPropsExpression).properties,
),
)
}
},
},
}
}
Copy the code
Step 3 (Package test)
- According to the
Ctrl
+Shift
+B
Select NPM: Build to wrap up our project code.
- in
babel-project/index.ts
To add a breakpoint anywhere, press F5
After the final execution is our plug-in modified code
lib/index.js
let b = /*#__PURE__*/React.createElement(PPP, null."1234");
let element = /*#__PURE__*/React.createElement(Button, {
color: "red"."size": "small" // This is added by our plugin
});
Copy the code
Well, reading this doesn’t teach you how to develop a Babel plug-in, only how to debug a simple Babel plug-in.