Managing multiple AWS-Lambda function on single node app using Serverless, ES6, Webpack, Babel

Serverless gif

Serverless architecture is the next step of cloud evolution. They can be service call, a communication tool between any of your database to any of your computing instance or whatever you want to call. It's called 'hype' technology in todays cloud community. I won't explain the whole technology but you can check Mike Roberts great blog about serverless.

In my case I wanted to use Amazon Web Service called 'Lambda' which gives you to automatically runs your code without requiring you to provision or manage servers. This functions can be written in Node.JS, Python, Java, Scala or C# runtimes. You can create those functions with Serverless Framework easily.

As a todays front-end & web developer you cannot hide yourself from javascript evolution. In multiple project I try to use next javascript version(called ES6) as much as possible.

Unfortunately AWS supports Node.JS 4.3 enviroment which doesn't fully support ES6. As you understood from title I'll show you my Webpack configuration that allows you to use & deploy multiple Lambda function inside single Node.js application using ES6.

In final let's imagine that you have folder structure like this

MyLambdaProject  
=================
/node_modules
/function1
   /node_modules
   lambda.js (This is where you write your ES6 code so Webpack can bundle to handler.js) 
   handler.js
   package.json
/function2
   /node_modules
   lambda.js (This is where you write your ES6 code so Webpack can bundle to handler.js) 
   handler.js
   package.json
webpack.config.js  
package.json  

Webpack configuration

You'll need the following npm packages.

{
  "name": "MyLambdaProject",
  "version": "1.0.0",
  "description": "This repository contains your lambda functions",
  "scripts": {
    "dev": "webpack --progress -p --watch"
  },
  "author": "OGPoyraz",
  "license": "MIT",
  "devDependencies": {
    "babel": "^6.5.2",
    "babel-cli": "^6.18.0",
    "babel-preset-latest": "^6.16.0",
    "json-loader": "^0.5.4",
    "path": "^0.12.7",
    "webpack": "^1.14.0"
  }
}

And your Webpack package is

const webpack = require("webpack"),  
    fs = require('fs'),
    path = require('path');

getDirectories = srcPath => {  
    return fs.readdirSync(srcPath).filter(file => {
        return file[0] == '.' || file == 'node_modules' ? false : fs.statSync(path.join(srcPath, file)).isDirectory();
    });
};

let shouldExcludeTheseModules = getDirectories('./').map(directory => {  
    return fs.readdirSync(`./${directory}/node_modules`)
});

module.exports = {  
    target: 'node',
    externals: shouldExcludeTheseModules,
    entry: {
        'function1/handler': './function1/lambda',
        'function2/handler': './function2/lambda'
    },
    output: {
        path: './',
        filename: '[name].js'
    },
    module: {
        loaders: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loaders: ['babel?presets[]=latest']
            },
            {
                test: /.json$/,
                loaders: ['json']
            }
        ],
    },
    plugins: [
        new webpack.DefinePlugin({
            'process.env': {
                'NODE_ENV': JSON.stringify('production')
            }
        })
    ]
};

When you have project structure like this you can run npm run dev so webpack can watch and bundle your javascript files in to spesific folder. It's important that you shouldn't forget to add your new lambda function to entry script inside your webpack.config.js

The key point in here is we exclude every single node_module from our bundled javascript file(handler.js) because AWS-Lambda allready handles when we use serverless deploy.

You can find the backbone of this project structure here.