Slide 1

Slide 1 text

Hello! My name is Mark, I hack on open source projects like the AVA test runner, and if I'm not doing that I work as a JavaScript-y contractor. This talk is about Babel plugins, and how to use them to do cool stuff beyond just supporting new syntax. Links: novemberborn.net / @novemberborn

Slide 2

Slide 2 text

Let's get the obvious out of the way: there are at least two correct ways of pronouncing Babel. The first is British English, the second American English. Make of that what you wish. I'll probably use both during the course of this talk. Links: http://dictionary.cambridge.org/pronunciation/english/babel

Slide 3

Slide 3 text

First let's look at how Babel works. Don't worry this will be very high level. There's three steps to running Babel.

Slide 4

Slide 4 text

Step zero: we start with code. This is just text, no plugin can deal with it.

Slide 5

Slide 5 text

To understand the code it needs to be parsed into an object structure. This is called an Abstract Syntax Tree. It describes everything in the text file, but because it's built of objects instead of bytes it can be manipulated. The parser follows the ECMAScript syntax rules. The AST must still represent valid JavaScript. Link: http://astexplorer.net/#/UwO26SGyJ5

Slide 6

Slide 6 text

Now that we have an AST it can be transformed. This creates a new AST. To do so we need to traverse the tree, looking for the nodes we're interested in. ArrowFunctionExpressions for instance. The latest preset creates a new AST that only contains ES5-compatible object.

Slide 7

Slide 7 text

Code is generated from the new AST. This can then be executed in a JavaScript runtime. This entire process is known as “transpilation".

Slide 8

Slide 8 text

By itself, Babel does nothing. Instead you need to pick a set of plugins. These can be grouped into presets. Link: https://babeljs.io/docs/plugins/

Slide 9

Slide 9 text

There are plugins available for all 5 stages of ECMAScript development. But, only the last stage (stage-4) is officially part of the language! Relying on unfinished features is risky: Babel could remove support. It gets worse. ES2015 modules are finished but Node.js doesn't support it. So, you use the transform-es2015-modules-commonjs plugin because you want to use the new syntax. There is no guarantee however that the implementation that ends up shipping in Node.js is compatible with your source code. You may need to keep transpiling it or otherwise refactor it so it can be used without running Babel on it first. Of course JavaScript is going to keep evolving, and even as fewer features need transpilation you may still want to keep Babel in your toolchain. In which case you'll probably be fine.

Slide 10

Slide 10 text

So far we've discussed, at a high level, how Babel works and what you need to look out for. If you're confident about having Babel in your stack, even if the environments you're targeting support the new syntax directly, then you've come to the right talk. (But it's single-track so you didn't really have much choice in the matter…) There's a wide range of plugins that do things beyond giving you early access to the new JavaScript shiny. Let's have a look at some examples.

Slide 11

Slide 11 text

The plugins you use may be other people's code, but they're definitely your problem. They may stop being maintained, in which case your code may stop working. You'll need to consider the cost of adopting a plugin, or moving away from one. You'll have more dependencies to install and keep up to date. Certain plugins may interfere with your linter setup, requiring additional configuration. With that out of the way, let's move on to some cool plugins you can use today.

Slide 12

Slide 12 text

Yup, the JSX syntax used by React is implemented as Babel plugin. But there are also plugins which can improve performance of your React code: transform-react-constant-elements ensures static elements are not unnecessarily recreated transform-react-inline-elements changes how elements are created to improve performance

Slide 13

Slide 13 text

The babel-plugin-lodash plugin lets you use the lodash module, but rewrites your code so it pulls in the underlying modules. This ensures your code only depends on the Lodash functionality that it uses.

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

This plugin, by Tommy Leunen, changes how modules are resolved. You can specify aliases for certain parts of your code base, making them easier to import. Link: https://github.com/tleunen/babel-plugin-module-resolver

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

Along the same line, I wrote a plugin that lets you import modules using a glob pattern. This is useful if you need to import multiple modules without needing explicit references to them. Link: https://github.com/novemberborn/babel-plugin-import-glob

Slide 18

Slide 18 text

In this example you could configure a router by adding a new module, without having to change the configuration code.

Slide 19

Slide 19 text

Plugins can be used for (micro) optimizations as well. The precompile- charcodes plugin by Ben Briggs precompiles character code lookups. Link: https://github.com/ben-eb/babel-plugin-precompile-charcodes

Slide 20

Slide 20 text

That said, don't go overboard. C style conditional compilation is a bit much.

Slide 21

Slide 21 text

The Babel Plugin Handbook has lot of detail on how to write plugins, including the APIs you need to use to transform the AST. The Babel REPL shows you how code is transformed using the official Babel plugins. Use this to get a feel for what Babel does to your code. AST Explorer lets you explore the AST for your source code. Be sure to select babylon6 as the parser.

Slide 22

Slide 22 text

Let's write a plugin of our own.

Slide 23

Slide 23 text

If you prefix your plugin name with babel-plugin- then your users don't have to repeat that in their Babel config. So let's do that. https://babeljs.io/docs/plugins/#plugin-preset-shorthand

Slide 24

Slide 24 text

What Node.js versions do you expect your plugin to run in? Please be explicit by setting the engines property in your package.json.

Slide 25

Slide 25 text

Similarly, what language features do you expect to be available when users run the generated code? Please document minimum Node.js or browser versions so users can make a proper decision on whether to rely on your plugin.

Slide 26

Slide 26 text

Also, changing your minimal requirements should be a breaking change.

Slide 27

Slide 27 text

Generally speaking, try to test the effects of your plugin, not the generated code. Generated code can change for reasons unrelated to your plugin's functioning. I've messed this up before. You could transform the code and then execute it using the VM module. Then write tests against the resulting value.

Slide 28

Slide 28 text

In this example the code is transpiled and then run as a script. Because it ends with foo, that value is returned as the result, and can then be compared against the expected value. See source.

Slide 29

Slide 29 text

I'd figure we'd try and do some maths with emojis. Turns out though that they're not valid identifiers! Link: http://astexplorer.net/#/4vXEBgI4EJ

Slide 30

Slide 30 text

This is more promising. Let's support emoji computation in template strings. It'll be clear that the output will be a string, and we can do maths using identifiers. If you look at the AST you'll see it's a BinaryExpression, with the right hand side being the clinking beer mugs emoji string, and the left being a TemplateLiteral. The literal contains just one BinaryExpression, which is the emoji maths. We need to find binary expressions inside template literals where either side is an emoji identifier, and there is some mathematical operator. Link: http://astexplorer.net/#/UgrB4UMDq5

Slide 31

Slide 31 text

Here’s the result of the live coding on AST Explorer: http:// astexplorer.net/#/nUF8VEm79L

Slide 32

Slide 32 text

Links: novemberborn.net / @novemberborn