Convenient way to use Babel syntax in Node.JS
Tags: node, javascript, babel, express
Published: 2019-07-28 15:19:27

When you want to use latest javascript syntax on the server side, typically you are offered two options: [babel-node](https://babeljs.io/docs/en/babel-node) or the [--experimental-modules flag](https://nodejs.org/api/esm.html). 
In this post I want to share another convenient way to use Babel in server applications trough a small library called [Pirates](https://github.com/ariporad/pirates)

## Hijack require

**Pirates** lets you create your own module loaders for any file types trough a simple API. Among other cool things, It can be used to pre-compile javascript files written with latest ES features. 

Consider following example:

```javascript
const {addHook} = require('pirates');

function matcher(filename) {
  // Here, you can inspect the filename to determine if it should be hooked or not. Just return a truthy/falsey. Files in node_modules are automatically ignored, 
  // TODO: Implement your logic here
  return true;
}

const unregister = addHook(
  (code, filename) => code.replace('@@foo', 'console.log(\'foo\');'), 
  { exts: ['.js'], matcher }
);

// And later, if you want to un-hook require, you can just do:
// unregister();

```

`addHook()` accepts two arguments: 1. A parser callback 2. An object with options.

## Setting up the project

Let's create an example ExpressJS project with Pirates.

#### 1. Installing Dependencies:
```bash
mkdir pirates-test && cd pirates-test
npm init
npm i pirates @babel/preset-env @babel/core express
```

#### 2. Add Babel hook
Create a file called `nodeHooks.js` with following content:

```javascript
    
const {addHook} = require('pirates')
const {transform} = require('@babel/core')

module.exports = (options) => addHook(
  function(source, filename) {
    return transform(source, {
      presets: [
        [
          '@babel/preset-env',
          {
            modules: 'cjs',
            targets: {
              node: process.versions.node
            }
          }
        ]
      ]
    }).code
  },
  {
    exts: ['.js'],
    ignoreNodeModules: true,
    ...options
  }
)
```
As you can see the hook function is not so different from a `.babelrc` configuration.

#### 3. Create an entry point for your application

Now before using Babel in the application we need to register the hook. Right way to do it would be to create an entry point for our application which would load all configurations and register hooks before running the server.

Create `index.js` with following content:
```javascript
const registerHooks = require('./nodeHooks')
registerHooks()

// load some configs synchronously 
// then run the server
 
require('./server')


``` 

#### 4. Write the application with Babel

Create `server.js` with following content:

```javascript
import express from 'express'

const app = express()

app.get('/', (req, res) => {
    res.send('Hello world!')
})

app.listen(8080)

export default app
```

Now the entire application can be written with latest ES features.

#### 5. Using nodemon

Use `nodemon` or your favourite process manager without extra steps: 

```bash
nodemon index.js
```


That's about it! 

[full code](https://github.com/nesterow/pirates-examle)