Skip to content

lifeomic/blamda

Repository files navigation

This package provides a simple CLI and Node API for bundling AWS Lambda services. Very quickly!

Usage

First, install the package.

yarn add -D @lifeomic/blamda

Now, bundle lambdas!

# Target a single file
yarn blamda --entries src/my-service.ts --outdir build-output --node 12

# Or, use a glob pattern
yarn blamda --entries "./src/lambdas/*" --outdir build-output --node 14

The output:

build-output/
  my-service.zip # Upload this to AWS!
  my-service/    # Or, package + upload this directory yourself.
    my-service.js

Node API

If you need deeper bundling customization, use the Node API.

import { bundle } from '@lifeomic/blamda';

bundle({
  entries: 'src/lambdas/*',
  outdir: 'build-output',
  node: 14,
  esbuild: {
    // Use this to override internal options passed to esbuild
  },
}).catch((err) => {
  console.error(err);
  process.exitCode = 1;
});

Build for Synthetics Canary

When deploying a lambda as Synthetics Canary, it requires the packaged js file saved under nodejs/node_modules within the packaged zip file. Please use the option artifactPrefix to specify the directory structure within the packaged zip file:

yarn blamda --entries src/my-service.ts --outdir build-output \
--artifact-prefix "nodejs/node_modules" --node 14

The output:

build-output/
  my-service.zip # Upload this to Synthetics Canary!
  my-service/    # Or, package + upload this directory yourself.
    nodejs/
      node_modules/
        my-service.js

Why Use This

As a pattern, bundling Lambda code provides a handful of benefits, especially in an environment with "many deploys":

  • Can provide performance optimizations. Many modern bundlers optimize the bundled code in non-trivial ways. These optimizations can result in Lambda handlers that execute more quickly.

  • Can significantly reduce code artifact size. This pays off in multiple ways:

    • Services stay below the default Lambda artifact file size limit (10GB).
    • Quicker deploys, thanks to smaller uploads.
    • Reduced cost of S3 storage of code artifacts, thanks to smaller file size.
  • Provides an opportunity to make easy Lambda environment-specific optimizations.

    • e.g. the aws-sdk module is "built-in" in to the Lambda environment. We can avoid bundling it and therefore significantly reduce bundle size.

Troubleshooting

Q: esbuild failed w/ error Could not resolve require("./src/build/**/*/DTraceProviderBindings"):

This happens when your app depends on dtrace-provider while building it on linux/windows w/ blamda.

To fix this, it needs to externalize this package by using a build script. For instance:

// build.js
const { bundle } = require('@lifeomic/blamda');

bundle({
  entries: 'src/*Lambda.ts',
  outdir: '../../deploy/terraform/build',
  node: 16,
  esbuild: {
    minify: true,
    sourcemap: 'inline',
    external: ['dtrace-provider'],  // exclude dtrace-provider
  },
}).catch((err) => {
  console.error(err);
  process.exitCode = 1;
});

Or using blamda CLI:

blamda --entries=src/*Lambda.ts --external=dtrace-provider