diff --git a/packages/@aws-cdk/aws-lambda-nodejs/README.md b/packages/@aws-cdk/aws-lambda-nodejs/README.md index aceb450596bb5..723ce157c6fbb 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/README.md +++ b/packages/@aws-cdk/aws-lambda-nodejs/README.md @@ -145,6 +145,10 @@ new lambda.NodejsFunction(this, 'my-handler', { }, logLevel: LogLevel.SILENT, // defaults to LogLevel.WARNING keepNames: true, // defaults to false + tsconfig: 'custom-tsconfig.json' // use custom-tsconfig.json instead of default, + metafile: true, // include meta file, defaults to false + banner : '/* comments */', // by default no comments are passed + footer : '/* comments */', // by default no comments are passed }, }); ``` diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts index 2620a37a81f67..137f641eb439a 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts @@ -54,6 +54,7 @@ export class Bundling implements cdk.BundlingOptions { public readonly local?: cdk.ILocalBundling; private readonly relativeEntryPath: string; + private readonly relativeTsconfigPath?: string; private readonly externals: string[]; constructor(private readonly props: BundlingProps) { @@ -64,6 +65,10 @@ export class Bundling implements cdk.BundlingOptions { const projectRoot = path.dirname(props.depsLockFilePath); this.relativeEntryPath = path.relative(projectRoot, path.resolve(props.entry)); + if (props.tsconfig) { + this.relativeTsconfigPath = path.relative(projectRoot, path.resolve(props.tsconfig)); + } + this.externals = [ ...props.externalModules ?? ['aws-sdk'], // Mark aws-sdk as external by default (available in the runtime) ...props.nodeModules ?? [], // Mark the modules that we are going to install as externals also @@ -140,6 +145,10 @@ export class Bundling implements cdk.BundlingOptions { ...loaders.map(([ext, name]) => `--loader:${ext}=${name}`), ...this.props.logLevel ? [`--log-level=${this.props.logLevel}`] : [], ...this.props.keepNames ? ['--keep-names'] : [], + ...this.relativeTsconfigPath ? [`--tsconfig=${pathJoin(inputDir, this.relativeTsconfigPath)}`] : [], + ...this.props.metafile ? [`--metafile=${pathJoin(outputDir, 'index.meta.json')}`] : [], + ...this.props.banner ? [`--banner='${this.props.banner}'`] : [], + ...this.props.footer ? [`--footer='${this.props.footer}'`] : [], ].join(' '); let depsCommand = ''; diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts index e71d6adbfee0c..f1008dc7b0368 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts @@ -66,6 +66,71 @@ export interface BundlingOptions { */ readonly keepNames?: boolean; + /** + * Normally the esbuild automatically discovers `tsconfig.json` files and reads their contents during a build. + * + * However, you can also configure a custom `tsconfig.json` file to use instead. + * + * This is similar to entry path, you need to provide path to your custom `tsconfig.json`. + * + * This can be useful if you need to do multiple builds of the same code with different settings. + * + * @example { 'tsconfig': 'path/custom.tsconfig.json' } + * + * @default - automatically discovered by `esbuild` + */ + readonly tsconfig? : string + + /** + * This option tells esbuild to write out a JSON file relative to output directory with metadata about the build. + * + * The metadata in this JSON file follows this schema (specified using TypeScript syntax): + * + * ```typescript + * { + * outputs: { + * [path: string]: { + * bytes: number + * inputs: { + * [path: string]: { bytesInOutput: number } + * } + * imports: { path: string }[] + * exports: string[] + * } + * } + * } + * } + * ``` + * This data can then be analyzed by other tools. For example, + * bundle buddy can consume esbuild's metadata format and generates a treemap visualization + * of the modules in your bundle and how much space each one takes up. + * @see https://esbuild.github.io/api/#metafile + * @default - false + */ + readonly metafile?: boolean + + /** + * Use this to insert an arbitrary string at the beginning of generated JavaScript files. + * + * This is similar to footer which inserts at the end instead of the beginning. + * + * This is commonly used to insert comments: + * + * @default - no comments are passed + */ + readonly banner? : string + + /** + * Use this to insert an arbitrary string at the end of generated JavaScript files. + * + * This is similar to banner which inserts at the beginning instead of the end. + * + * This is commonly used to insert comments + * + * @default - no comments are passed + */ + readonly footer? : string + /** * Environment variables defined when bundling runs. * @@ -83,7 +148,7 @@ export interface BundlingOptions { /** * A list of modules that should be installed instead of bundled. Modules are - * installed in a Lambda compatible environnment only when bundling runs in + * installed in a Lambda compatible environment only when bundling runs in * Docker. * * @default - all modules are bundled diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts b/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts index 3f999de35c07c..e3f6a07144b88 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts @@ -28,6 +28,7 @@ beforeEach(() => { let depsLockFilePath = '/project/yarn.lock'; let entry = '/project/lib/handler.ts'; +let tsconfig = '/project/lib/custom-tsconfig.ts'; test('esbuild bundling in Docker', () => { Bundling.bundle({ @@ -161,6 +162,10 @@ test('esbuild bundling with esbuild options', () => { }, logLevel: LogLevel.SILENT, keepNames: true, + tsconfig, + metafile: true, + banner: '/* comments */', + footer: '/* comments */', forceDockerBundling: true, }); @@ -174,7 +179,8 @@ test('esbuild bundling with esbuild options', () => { 'npx esbuild --bundle /asset-input/lib/handler.ts', '--target=es2020 --platform=node --outfile=/asset-output/index.js', '--minify --sourcemap --external:aws-sdk --loader:.png=dataurl', - '--log-level=silent --keep-names', + '--log-level=silent --keep-names --tsconfig=/asset-input/lib/custom-tsconfig.ts', + '--metafile=/asset-output/index.meta.json --banner=\'/* comments */\' --footer=\'/* comments */\'', ].join(' '), ], }),