npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

lerna-to-lambda

v0.3.1

Published

Build standalone code packages from lerna monorepos

Downloads

3,813

Readme

lerna-to-lambda (l2l)

The problem

I want to build AWS Lambda function zip files for individual packages in my lerna monorepo. I could zip the entire monorepo with its dependencies, using a different entry point for each Lambda function, but that may be too large. I could copy each package into a separate directory and run yarn --production in it, but this will lead to problems with my internally referenced libraries contained by the monorepo. What I really want is a tool that will help bundle a package with exactly the dependencies it needs, whether they come from external packages or the monorepo.

Usage

Add lerna-to-lambda as a dev dependency to the root of the lerna project:

yarn add -W --dev lerna-to-lambda

At the necessary point in your workflow, run a packaging step which executes l2l with the appropriate options. For example, for a Lambda function written in TypeScript, with tsc configured to output JavaScript to a folder named build, the package.json could include something like this:

"scripts": {
  ...
  "clean": "rimraf build lambda",
  "compile": "tsc -p tsconfig.build.json",
  "package": "l2l -i build -o lambda",
  "build": "yarn run clean && yarn run compile && yarn run package"
},

This l2l command will copy everything from build into lambda, then populate lambda/node_modules with all of the dependencies specified in package.json as well as all of their recursive subdependencies. By default, l2l will omit the dependency aws-sdk and subdependencies which strictly originate from it because these are already provided by the standard Lambda containers. The resulting lambda directory should be a standalone application which is ready to ship to Lambda.

Running yarn l2l --help in your project will show the full list of options.

What It's Not

This is not a package manager. l2l does not install packages or verify that the proper dependency versions are fulfilled. You must accomplish that via other means such as yarn before running l2l. Ideally, if you have the correct dependencies installed in your project, such that you are able to run your script locally, then running l2l on it will generate a folder which can do the same thing on its own. That's all it does.

What's Even Weirder

The topology of your dependencies might shift during the bundling process. This is because we are going from a hierarchy with two layers of node_modules down to only one. Specifically, consider the following scenario:

  • Packages A and B are Lambda scripts which both depend on common library package C
  • Packages B and C depend on version X of third-party package D, which lerna hoists
  • Package A depends on version Y of third-party package D, which lerna does not hoist
  • Package A also depends on third-party package E, which is hoisted

This would lead to a structure like:

/node_modules/C -> ../packages/C (symlink)
/node_modules/D
/node_modules/E
/packages/A/node_modules/D
/packages/B
/packages/C

When l2l bundles package A, it will start by copying all of A's direct dependencies (without their subdependencies) into the node_modules directory of the bundle:

outdir/node_modules/C (copied from /packages/C)
outdir/node_modules/D (copied from /packages/A/node_modules/D)
outdir/node_modules/E (copied from /node_modules/E)

Next l2l will recursively copy subdependencies, but it will immediately run into a conflict. Package C's subdependency on D resolves to /node_modules/D, but we've already copied /packages/A/node_modules/D to outdir/node_modules/D. There is no higher level node_modules in our bundle to store the lerna-hoisted packages, so instead l2l will "unhoist" C's subdependency:

outdir/node_modules/C/node_modules/D (copied from /node_modules/D)

It is possible to contrive scenarios in which this reorganization could make packages less efficient or potentially even break them. It's also important to note that l2l does not install the node_modules/.bin directories or any of the related symlinks. This should not matter to most projects, but if a Lambda script is explicitly executing something from there, it will not bundle properly.