Slide 1

Slide 1 text

Writing Babel Plugin YWC Programmer Meetup

Slide 2

Slide 2 text

Why Babel?

Slide 3

Slide 3 text

Write code that you hate to write a.k.a Syntactic Sugar

Slide 4

Slide 4 text

Some use of Babel #connect people to good stuff ● ES6 const A = () => {} → var A = function A() {} ● JSX
→ React.createElement("div", null); ● Individually import Lodash functions import { add } from 'lodash/fp' → import _add from 'lodash/fp/add' ● Generate data-qa tags for automated test selection

Slide 5

Slide 5 text

Let’s write a plugin!

Slide 6

Slide 6 text

Parsing How your computer understand your code

Slide 7

Slide 7 text

JSON #connect people to good stuff let data = JSON.parse('{"hello": "world"}') data.hello

Slide 8

Slide 8 text

XML #connect people to good stuff let data = new DOMParser() .parseFromString("hello", "application/xml"); data.documentElement.textContent

Slide 9

Slide 9 text

Source code?? #connect people to good stuff import { parse } from '@babel/parser' parse('console.log("hello")') ???

Slide 10

Slide 10 text

Abstract Syntax Tree (AST) #connect people to good stuff ● Code is represented by AST ● astexplorer.net ● ⚠ Make sure you set parser to babel-eslint

Slide 11

Slide 11 text

console.log("hello world") type: Program body: - type: ExpressionStatement expression: type: CallExpression callee: type: MemberExpression object: type: Identifier name: console property: type: Identifier name: log arguments: - type: Literal value: hello world * Some fields are omitted #connect people to good stuff

Slide 12

Slide 12 text

console.log("hello world") type: Program body: - type: ExpressionStatement expression: type: CallExpression callee: type: MemberExpression object: type: Identifier name: console property: type: Identifier name: log arguments: - type: Literal value: hello world #connect people to good stuff

Slide 13

Slide 13 text

console.log("hello world") type: Program body: - type: ExpressionStatement expression: type: CallExpression callee: type: MemberExpression object: type: Identifier name: console property: type: Identifier name: log arguments: - type: Literal value: hello world #connect people to good stuff

Slide 14

Slide 14 text

console.log("hello world") type: Program body: - type: ExpressionStatement expression: type: CallExpression callee: type: MemberExpression object: type: Identifier name: console property: type: Identifier name: log arguments: - type: Literal value: hello world #connect people to good stuff

Slide 15

Slide 15 text

console.log("hello world") type: Program body: - type: ExpressionStatement expression: type: CallExpression callee: type: MemberExpression object: type: Identifier name: console property: type: Identifier name: log arguments: - type: Literal value: hello world #connect people to good stuff

Slide 16

Slide 16 text

console.log("hello world") type: Program body: - type: ExpressionStatement expression: type: CallExpression callee: type: MemberExpression object: type: Identifier name: console property: type: Identifier name: log arguments: - type: Literal value: hello world #connect people to good stuff

Slide 17

Slide 17 text

Transform

Slide 18

Slide 18 text

Babel Plugin #connect people to good stuff ● Babel plugin is just a JavaScript file with default export export default function({ types: t }) { return { visitor: { // visitor contents } }; };

Slide 19

Slide 19 text

Babel Plugin #connect people to good stuff ● Provide visitor functions for interested node type export default function({ types: t }) { return { visitor: { Identifier(path, state) {}, } }; };

Slide 20

Slide 20 text

Goal #connect people to good stuff $("id") → document.getElementById("id")

Slide 21

Slide 21 text

Know the AST #connect people to good stuff type: Program body: - type: ExpressionStatement expression: type: CallExpression callee: type: Identifier name: $ arguments: - type: Literal value: id

Slide 22

Slide 22 text

Babel Plugin #connect people to good stuff Match CallExpression export default function({ types: t }) { return { visitor: { CallExpression(path, state) { // ... }, } }; }; type: Program body: - type: ExpressionStatement expression: type: CallExpression callee: type: Identifier name: $ arguments: - type: Literal value: id

Slide 23

Slide 23 text

Babel Plugin #connect people to good stuff Use t (@babel/types) to build nodes export default function({ types: t }) { return { visitor: { CallExpression(path, state) { // ... }, } }; }; type: Program body: - type: ExpressionStatement expression: type: CallExpression callee: type: Identifier name: $ arguments: - type: Literal value: id

Slide 24

Slide 24 text

Babel Plugin #connect people to good stuff Match callee that it is $ identifier CallExpression(path, state) { if ( t.isIdentifier( path.node.callee, { name: '$' } ) ){ // ... } }, type: Program body: - type: ExpressionStatement expression: type: CallExpression callee: type: Identifier name: $ arguments: - type: Literal value: id

Slide 25

Slide 25 text

type: Program body: - type: ExpressionStatement expression: type: CallExpression callee: type: MemberExpression object: type: Identifier name: document property: type: Identifier name: getElementById arguments: - type: Literal value: id Babel Plugin #connect people to good stuff Replace with document.getElementById CallExpression(path, state) { if (t.isIdentifier(path.node.callee, {name: '$'})){ path.node.callee = t.memberExpression( t.identifier('document'), t.identifier('getElementById') ) } },

Slide 26

Slide 26 text

Running #connect people to good stuff ● Put the plugin file in babel.config.js ● Be careful of Babel cache in node_modules/.cache

Slide 27

Slide 27 text

Uses of Babel plugins at Wongnai

Slide 28

Slide 28 text

Babel uses at Wongnai #connect people to good stuff ● Lodash per-function import babel-plugin-lodash ● Generate data-qa tags for automated test selection babel-plugin-transform-react-qa-classes ● Compile time locale split/inlining Read more on life.wongnai.com

Slide 29

Slide 29 text

Thank You Grab this deck at https://speakerdeck.com/whs