(aws-lambda-nodejs): export esbuild asset code bundler
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 71
Description
Can't use aws-lambda-nodejs' capabilities in Lambda@Edge.
### Use Case
If you want to use a NodeJS lambda in edge, you need to bundle the code by yourself. It'd be ideal to export the esbuild bundling functionality so anybody can create the AssetCode with esbuild and use it on any other lambda functions such as Lambda@Edge.
### Proposed Solution
Just exporting the class `Bundling` in `@aws-cdk/aws-lambda-nodejs` would be enough. As a workaround, I did this, which is heavily based on the current implementation but uses esbuild's JS API:
```ts
import * as lambda from "@aws-cdk/aws-lambda";
import * as cdk from "@aws-cdk/core";
import * as esbuild from "esbuild";
import findUp from "find-up";
import * as path from "path";
const findDepsLockFilePath = (input: string) => {
const lockFilePath = findUp.sync(["package-lock.json", "yarn.lock"], {
cwd: input,
});
if (!lockFilePath) {
throw new Error("Couldn't find a lock file (package-lock.json or yarn.lock)");
}
return lockFilePath;
};
/**
* Converts a Lambda runtime to an esbuild node target.
*/
function toTarget(runtime: lambda.Runtime): string {
const match = runtime.name.match(/nodejs(\d+)/);
if (!match) throw new Error("Cannot extract version from runtime.");
return `node${match[1]}`;
}
export interface EsbuildBundlingProps {
input: string;
runtime: lambda.Runtime;
external?: string[];
define?: {
[key: string]: string;
};
}
export class EsbuildBundling {
public static bundle(options: EsbuildBundlingProps): lambda.AssetCode {
const depsLockFilePath = findDepsLockFilePath(options.input);
return lambda.Code.fromAsset(path.dirname(depsLockFilePath), {
assetHashType: cdk.AssetHashType.OUTPUT,
bundling: new EsbuildBundling(options),
});
}
public readonly image: cdk.DockerImage;
public readonly local: cdk.ILocalBundling;
constructor(private readonly props: EsbuildBundlingProps) {
this.image = cdk.DockerImage.fromRegistry("dummy");
this.local = {
tryBundle(outputDir) {
console.log({ outputDir, input: props.input });
esbuild.buildSync({
entryPoints: [props.input],
bundle: true,
platform: "node",
target: toTarget(props.runtime),
outfile: `${outputDir}/index.js`,
external: ["aws-sdk", ...(props.external || [])],
define: props.define,
// minify: true,
});
return true;
},
};
}
}
```
### Other
* [x] :wave: I may be able to implement this feature request
* [ ] :warning: This feature might incur a breaking change
---
This is a :rocket: Feature Request
Contributor guide
Research direction
Start by locating the existing Bundling class and the public exports for @aws-cdk/aws-lambda-nodejs, then inspect how its current implementation is used. Done means the bundling functionality can be imported publicly and used to create AssetCode for Lambda@Edge or other Lambda functions.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, typescript
- Domain
- backend, cloud
- Issue type
- Feature
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100