Babel Plugins: More than just ES2016

Babel Plugins: More than just ES2016

This talk is about Babel plugins, and how to use them to do cool stuff beyond just supporting new syntax.

Ad418e3e53e0ba71ba56b7df978671e8?s=128

Mark Wubben

November 18, 2016
Tweet

Transcript

  1. 1.

    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
  2. 2.

    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
  3. 3.

    First let's look at how Babel works. Don't worry this

    will be very high level. There's three steps to running Babel.
  4. 4.
  5. 5.

    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
  6. 6.

    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.
  7. 7.

    Code is generated from the new AST. This can then

    be executed in a JavaScript runtime. This entire process is known as “transpilation".
  8. 8.

    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/
  9. 9.

    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.
  10. 10.

    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.
  11. 11.

    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.
  12. 12.

    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
  13. 13.

    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.
  14. 14.
  15. 15.

    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
  16. 16.
  17. 17.

    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
  18. 18.

    In this example you could configure a router by adding

    a new module, without having to change the configuration code.
  19. 19.

    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
  20. 21.

    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.
  21. 23.

    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
  22. 24.

    What Node.js versions do you expect your plugin to run

    in? Please be explicit by setting the engines property in your package.json.
  23. 25.

    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.
  24. 27.

    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.
  25. 28.

    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.
  26. 29.

    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
  27. 30.

    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
  28. 31.

    Here’s the result of the live coding on AST Explorer:

    http:// astexplorer.net/#/nUF8VEm79L