WarsawJS Slides: Babel.js

We talk about JavaScript. Each month in Warsaw, Poland.

Speaker

Andriy Mykulyak

"Babel.js - a (not so) short introduction"

2017-07-12

@amykulyak LinkedIn Gmail

Who am I ?

Senior software consultant

@ Shedul.com, Warsaw

Full stack developer. Like challenges, JavaScript and Python.
Privately is passionate about triathlon.

"Do. Or do not. There is no try" (c) Yoda

What is Babel.js ?

Babel is a JavaScript transpiler.

Sure, it can convert ES8 code to ES5 ... but not only !

It is essentially a platform for developing future EcmaScript language and tooling.

Why use Babel ?

How it works ?

Asany compiler, Babel consists of several parts:

  1. tokenizer breaks source text into a stream tokens. babylon is the Babel's tokenizer

Usage

Command line usage - babel

        
            > npm install babel-cli
            > babel inscript.js -o outscript.js // transpile
            > babel indir -o outfile.js // transpile & concatenate
            > babel --watch indir -o outscript.js // watch & transpile & concatenate
        
    

Many other options are allowed.

Often used in prepublish scripts for packages targeted to Node runtime. Watch mode is useful when working on multiple "ad-hoc" scripts

Command line usage - babel-node

        
            > npm install babel-node

            > babel-node es8-script.js
        
    

It is like a node with babel inside. Mostly for one-off scripts ...

Using via babel-register

        
            // entry-point.js - still have to use require()
            require('babel-register');
            require('./es8-script.js');

            // es8-script.js - magic happens here
            console.log('123'.padStart(6, ' '));
        
    

Babel intercepts require() calls and transpiles modules on the fly. Transpiled modules are cached on disk. This mechanism does not work in a browser.

Using API

        
            import babel from 'babel-core';

            const {
                code, // resulting code
                map, // source map
                ast // resulting AST (abstract syntaxt tree)
            } = babel.transform(sourceCode, options);
        
    

How AST looks like.

Other top-level API

        
            babel.transformFile(filename, options, callback);

            const { code, map, ast } =
                babel.transformFileSync(filename, options);

            const { code, map, ast } =
                babel.transformFromAST(ast, code, options);
        
    

Configuration

By default Babel.js does nothing ...

... because all the power is in plugins !

... and before using, one should configure them !

Configuration via .babelrc

        
            {
                "presets": ["env", "react"],
                "env": {
                    "production": {
                        // strip assertions & minify
                        "plugins": ["babel-plugin-unassert"],
                        "presets": ["babili", "env", "react"]
                    }
                },
                ...
            }
        
    

Configuration via .babelrc

.babelrc is a JSON5 (user-friendly JSON). Babel 7 should support configuration in JavaScript - .babelrc.js

Plugins can have options.

        
            [ "env", { "targets": { "node": "current" } },
        
    

Order of plugins and presets does matter ! Plugins runs firstly in left-to-right order in the configuration, presets run after plugins in the right-to-left order.

Multiple .babelrc files

        
            /src
                // top-level .babelrc is used here
                ...
                /legacy
                    ...
                    .babelrc // this file is used for legacy subtree
                             // which e.g. may have less transforms
            ...
            .babelrc
        
    

Multiple .babelrc files

If there is more than one .babelrc file, only the "closest" one (up the folder tree) is used !

Helps for projects with several distinct parts (e.g. Express app with client and server parts, legacy subsystem, React code, etc.)

Configuration in package.json

        
            {
                "name": "some-package",
                "babel": {     // top-level key only
                    ...
                },
                ...
            }
        
    

Options from .babelrc have priority over those from package.json.

Configuration using babel-register

        
            require('babel-register')({
                plugins: ['env'],
                ...
                ignore: /^ignore-me\/.*\.js$/,
                only: /^compile-only-me\/.*\.js$/,
                extensions: ['.js', '.jsx'],
                cache: true
            });
        
    

Plugins

Plugin do code transformations !

Every Babel.js transformation in Babel.js is done by some plugin !

Preset is a name for group of plugins used simultaneously.

(Most important) official presets

babel-preset-env

Takes target environment specification and the current language standard version to determine plugins needed. We can in principle stop unsing es20XX presets

        
            "plugins": [
                ["env", {
                    "targets": {
                        "browsers": ["ie > 10", "> 1%"],
                        "node": "6"
                    }
                }]
            ]
        
    

Custom presets

Everyone can create custom presets !

They help enforce consistent environments.

Essentially, you need a NPM package with 2 files - package.json and index.js.

Custom preset - package.json

        
            {
                "name": "@your-scope/babel-preset-your-preset",
                "version": "1.2.3",
                ...
                "dependencies": {
                    "babel-preset-env": "^1.6.0",
                    "babel-preset-react": "^6.23.0",
                    ...
                }
            }
        
    

Custom preset - index.js

        
            module.exports = {
                presets: [
                    ['env', {
                        targets: {
                            browsers: ['> 1%']
                        }
                    }],
                    'react'
                ]
            };
        
    

Community plugins

Yesterday there were more than 1700 packages for Babel

Community plugins - unassert

babel-plugin-unassert - removes assertions from source code

babel-plugin-react-intl - extracts literals for translation from React projects

babel-plugin-istanbul - add Instanbul coverage code

Other projects

Useful Links

Thank you

See you next month at WarsawJS

Codemod power

remove debugger statements


        export default function ({ path, source }, { jscodeshift: j }, options) {
            return j(source).find(j.DebuggerStatement).forEach(path => {
                j(path).remove();
            }).toSource();
        };