Building AWS Serverless applications with NX Dev Tools on a monorepo

NX, Serverless and Lambda for serverless architecture

A monorepo can be described as a repository that contains more than one logical project. These projects can be unrelated, loosely coupled or connected by dependency management tools, they are usually large in size, branches, commits, and working developers.

Serverless computing such as AWS Serverless offers a number of advantages over traditional cloud-based or server-centric infrastructure. For many developers, serverless architectures offer greater scalability, more flexibility, and quicker time to release, all at a reduced cost. With serverless architectures, developers do not need to worry about purchasing, provisioning, and managing backend servers.

This article will guide how to build AWS Serverless Application using Nx Dev Tool Extension and Serverless Framework.

Creating Workspace and Library with Nx

Command create a workspace.

npm init nx-workspace myworkspace

In this example, I use the empty workspace and Angular CLI (If you use VSCode, you can use Angular Console plugin to generate apps, libs,…).

With an empty Nx workspace, there are no applications to build, serve, and test. Command add node application capabilities to the workspace.

cd myworkspace && npm install --save-dev @nrwl/node

After the capability is added, I create two applications.

ng g @nrwl/node:application hello-app
ng g @nrwl/node:application greeting-app

And a library.

ng g @nrwl/workspace:lib common-util

Applying the Serverless framework to the workspace

To build AWS Serverless Application with Serverless Framework, the application needs a serverless.yml file.

In hello-app directory, Adding serverless.yml file with the content.

service: hello-app
provider:
  name: aws
  runtime: nodejs10.x
  stage: dev
  region: us-east-1
  webpack:
    webpackConfig: 'webpack.config.js'
    includeModules: true
    packager: 'npm'
    packExternalModulesMaxBuffer: 204800 
functions:
  hello: ${file(apps/hello-app/src/functions/hello/hello.yml)}
plugins:
  - serverless-webpack

Similarly, add serverless.yml to greeting-app directory.

// Update
service: greeting-app
...
functions:
  greeting: ${file(apps/greeting-app/src/functions/greeting/greeting.yml)}

Add libraries for AWS and Serverless.

npm install --save aws-lambda
npm install --save-dev serverless serverless-webpack tsconfig-paths-webpack-plugin

You can see more detail about serverless plugin here. Then add a webpack.config.js file at workspace root directory.

const path = require('path');
const slsw = require('serverless-webpack');
const nodeExternals = require('webpack-node-externals');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');

module.exports = {
  externals: [nodeExternals()],
  devtool: 'source-map',
  entry: slsw.lib.entries,
  resolve: {
    extensions: ['.js', '.json', '.ts', '.tsx'],
    plugins: [
      new TsconfigPathsPlugin()
    ]
  },
  target: 'node',
  module: {
    rules: [
      {
        test: /\.ts(x?)$/,
        use: [
          {
            loader: 'ts-loader'
          }
        ]
      }
    ]
  },
  plugins: [],
  mode: slsw.lib.webpack.isLocal ? 'development' : 'production',
  stats: 'minimal', // errors-only, minimal, none, normal, verbose
  output: {
    libraryTarget: 'commonjs',
    path: path.resolve(__dirname, '.webpack'),
    filename: '[name].js'
  }
};

See serverless-webpack for more detail.

The workspace structure.

To illustrate how useful libraries can be. Updating common-util.ts file in the common-util library.

export const getMessage = () => {
  return 'This is a message from workspace library';
};

Add hello.handler.ts, hello.yml, and index.ts file to functions/hello directory and also refer to the common-util library, see below code snippet:

//hello.handler.ts
import { Handler, Context } from 'aws-lambda';
import { getMessage } from '@myworkspace/common-util';

export const handler: Handler = async (event: any, context: Context) => {
  return {
    statusCode: 200,
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ message: getMessage() })
  };
};

//hello.yml
handler: apps/hello-app/src/functions/hello/index.handler
description: A function for Hello Application
events:
  - http:
      path: /hello
      method: get

//index.ts
export * from './hello.handler';

Similarly, Add greeting.handler.ts, greeting.yml, and index.ts file to functions/greeting directory with content as hello.handler.ts, hello.yml.

Deploying

To deploy AWS Serverless Application with Serverless Framework you need to install AWS CLI and config AWS Credential. Because every application is separated, so I can deploy separately for every application.

sls deploy --config apps/hello-app/serverless.yml
sls deploy --config apps/greeting-app/serverless.yml

Result:

Conclusion

In this guide, AWS Serverless Application is built with awesome tools and patterns that will make our life as developers pretty enjoyable.

About Author:

2 thoughts on “Building AWS Serverless applications with NX Dev Tools on a monorepo

  1. Hey, thanks a bunch for this. Great and well needed resource in the nx monorepo community.

    I seem to be getting an error when I run my lamdba function:

    “Runtime.ImportModuleError: Error: Cannot find module ‘tslib'”,”

    Even though tslib is part of my deps (not dev deps)

    Any ideas?

  2. Hi thanks for share.
    But what if using serverless-bundle? How to properly config the project and tsconfig-paths-webpack-plugin?

Leave a Comment

Your email address will not be published. Required fields are marked *