I use Babel, a JavaScript compiler, in order to write bleeding-edge JavaScript which runs well on a variety of targets. I have a go-to setup for Node which has a few neat features that makes code easier to read and maintain.

Core Setup

To start, I pull in the following under devDependencies in my package.json file:

"devDependencies": {
    "@babel/cli": "^7.2.3", // Make sure to pull the latest stable release
    "@babel/core": "^7.2.2", // which at the time of writing was v7.
    "@babel/node": "^7.2.2",
    "@babel/preset-env": "^7.3.1",
    ...
}

Plugins

Now that I've gotten the base setup going, I add a couple plugins which enable features with which I really like to work:

Class Properties

Adding the @babel/plugin-proposal-class-properties plugin allows me to use static class properties – syntax that I often reach for:

Adding this:

"devDependencies": {
    ...
    "@babel/plugin-proposal-class-properties": "^7.3.0",
}

Allows us to use:

export class Example {
  static getArray () {
    return [1, 2, 3]
  }
}

Module Resolver

Another plugin near-and-dear to my heart is the babel-plugin-module-resolver which allows me to alias directories for my modules – gets me out of the ../../../dot-hell mess!

Adding this:

"devDependencies": {
    ...
    "babel-plugin-module-resolver": "^3.1.3",
}

Allows us to use:

// We look at how to set up the "@" alias in the Configuration section below
import { Example } from '@/models/Example'

Configuration

Great! Now that we're all set up, we need to configure Babel. I chose to use a babel.config.js configuration file as opposed to .babelrc since it allows for comments, programmatic creation, and keeps it more succinct. For the above setup, I would use the following configuration:

module.exports = function (api) {
  api.cache(true)

  const presets = ['@babel/preset-env']
  
  const plugins = [
    [require.resolve('@babel/plugin-proposal-class-properties')],
    [require.resolve('babel-plugin-module-resolver'),
      {
        'root': ['./src'], // !! This is where we're setting the "@" alias!
        'alias': {
          '@': './src'
        }
      }
    ]
  ]

  return {
    presets,
    plugins
  }
}

As you can see, we're configuring the presets and the plugins here – both of which we export – and telling the system to cache the configuration. And notice that we've aliased @ to our src directory so just like that, we can avoid the trailing-dot hell.

Running Babel

Sweet, we're all set! Last thing I do is to create a few scripts which will actually run our code through Babel during development and before deploying.

Note: I'm using nodemon for development which is an amazing tool to monitor and reload the Node server automatically after file changes.
"scripts": {
    "start": "nodemon --exec babel-node src/index.js", // Point towards entry file
    "build": "node_modules/@babel/cli/bin/babel.js src --out-dir dist",
  }

That's a wrap! This Babel setup is pretty quick to get running and I find it very helpful when reaching for bleeding-edge JavaScript functionality.