-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
(aws-lambda-nodejs): export esbuild asset code bundler #14215
Comments
This is a nice idea and could also be helpful if you are building your own layers, where you want to bundle your code the same way you do in lambda! |
I am unassigning and marking this issue as We use +1s to help prioritize our work, and are happy to revaluate this issue based on community feedback. You can reach out to the cdk.dev community on Slack to solicit support for reprioritization. |
I don't really understand why it's low priority. How do you guys do with v2 ? Any workaround ? |
Exporting the import path from "node:path";
import { AssetHashType, DockerImage, ILocalBundling } from "aws-cdk-lib";
import { experimental } from "aws-cdk-lib/aws-cloudfront";
import { FunctionOptions, Runtime, Code, AssetCode } from "aws-cdk-lib/aws-lambda";
import { Construct } from "constructs";
import { buildSync } from "esbuild";
import { findUpSync } from "find-up";
const findDepsLockFilePath = (input: string) => {
const lockFilePath = findUpSync(["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: 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: Runtime;
external?: string[];
define?: {
[key: string]: string;
};
}
export class EsbuildBundling {
public static bundle(options: EsbuildBundlingProps): AssetCode {
const depsLockFilePath = findDepsLockFilePath(options.input);
return Code.fromAsset(path.dirname(depsLockFilePath), {
assetHashType: AssetHashType.OUTPUT,
bundling: new EsbuildBundling(options)
});
}
public readonly image: DockerImage;
public readonly local: ILocalBundling;
constructor(private readonly props: EsbuildBundlingProps) {
this.image = DockerImage.fromRegistry("dummy");
this.local = {
tryBundle(outputDir) {
//console.log({ outputDir, input: props.input }, props);
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;
}
};
}
}
/**
* environment variables are not supported for Lambda@Edge
*/
export interface NodejsEdgeFunctionProps extends Omit<FunctionOptions, "environment"> {
/**
* Path to the entry file (JavaScript or TypeScript).
*
* @default - Derived from the name of the defining file and the construct's id.
* If the `NodejsFunction` is defined in `stack.ts` with `my-handler` as id
* (`new NodejsFunction(this, 'my-handler')`), the construct will look at `stack.my-handler.ts`
* and `stack.my-handler.js`.
*/
readonly entry?: string;
/**
* The name of the exported handler in the entry file.
*
* @default handler
*/
readonly handler?: string;
/**
* The runtime environment. Only runtimes of the Node.js family are
* supported.
*
* @default Runtime.NODEJS_14_X
*/
readonly runtime?: Runtime;
/**
* Whether to automatically reuse TCP connections when working with the AWS
* SDK for JavaScript.
*
* This sets the `AWS_NODEJS_CONNECTION_REUSE_ENABLED` environment variable
* to `1`.
*
* @see https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/node-reusing-connections.html
*
* @default true
*/
readonly awsSdkConnectionReuse?: boolean;
/**
* The path to the dependencies lock file (`yarn.lock` or `package-lock.json`).
*
* This will be used as the source for the volume mounted in the Docker
* container.
*
* Modules specified in `nodeModules` will be installed using the right
* installer (`npm` or `yarn`) along with this lock file.
*
* @default - the path is found by walking up parent directories searching for
* a `yarn.lock` or `package-lock.json` file
*/
readonly depsLockFilePath?: string;
/**
* Bundling options
*
* @default - use default bundling options: no minify, no sourcemap, all
* modules are bundled.
*/
readonly bundling?: EsbuildBundlingProps;
/**
* The path to the directory containing project config files (`package.json` or `tsconfig.json`)
*
* @default - the directory containing the `depsLockFilePath`
*/
readonly projectRoot?: string;
/**
* The stack ID of Lambda@Edge function.
*
* @default - `edge-lambda-stack-${region}`
* @stability stable
*/
readonly stackId?: string;
}
export class NodejsEdgeFunction extends experimental.EdgeFunction {
constructor(scope: Construct, id: string, props: NodejsEdgeFunctionProps) {
const handler = props.handler ?? "handler";
const runtime = props.runtime ?? Runtime.NODEJS_16_X;
super(scope, id, {
...props,
runtime,
stackId: props.stackId,
code: EsbuildBundling.bundle({
...props.bundling
}),
handler: `index.${handler}`
});
}
} |
I used '@mrgrain/cdk-esbuild:
|
This issue has received a significant amount of attention so we are automatically upgrading its priority. A member of the community will see the re-prioritization and provide an update on the issue. |
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:Other
This is a 🚀 Feature Request
The text was updated successfully, but these errors were encountered: