I recently needed to use a Node-based Lambda where it depended on an NPM module.
I didn't wan't to begin using a bundler, switch runtimes or do any workarounds. I just needed to get this custom resource up and running.
Note
I'm not sure whether this whole approach is overkill and could be better accomplished by using URL-based imports. At the time of writing, I haven't seen a URL-based imports except in Deno.
The following script installs the NPM packages into a directory called nodejs
,
packs it into an archive and then uploads it. The script is rather crude and publishes
a new version of the layer on every invocation.
#!/bin/bash
# Variables
LAYER_NAME="adm-zip-layer"
RUNTIME="nodejs20.x" # Change this to your Lambda's runtime
TEMP_DIR="adm-zip-layer"
ZIP_FILE="adm-zip-layer.zip"
# Step 1: Create directory structure
mkdir -p $TEMP_DIR/nodejs
# Step 2: Install adm-zip and dependencies into the nodejs folder
npm install adm-zip --prefix $TEMP_DIR/nodejs
npm install minimatch --prefix $TEMP_DIR/nodejs
npm install mime-types --prefix $TEMP_DIR/nodejs
# Step 3: Package the layer
cd $TEMP_DIR
zip -r ../$ZIP_FILE nodejs
cd ..
# Step 4: Publish the layer to AWS
aws lambda publish-layer-version --layer-name $LAYER_NAME \
--zip-file fileb://$ZIP_FILE \
--compatible-runtimes $RUNTIME
# Cleanup
rm -rf $TEMP_DIR
rm $ZIP_FILE
echo "Lambda layer $LAYER_NAME published successfully."
I just wanted to sanity check if this in fact is possible so I just queried ChatGPT. https://chatgpt.com/share/67062a1f-ae70-8006-80c6-0d754f3720f3
I've come to the conclusion that packing additional dependencies is the correct way.