Skip to content

Commit

Permalink
chore(lambda-nodejs): use bundling from core (aws#8576)
Browse files Browse the repository at this point in the history
Refactor to use bundling from `core`.


----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
jogold authored Jun 17, 2020
1 parent e91212f commit 5491922
Show file tree
Hide file tree
Showing 6 changed files with 241 additions and 362 deletions.
178 changes: 0 additions & 178 deletions packages/@aws-cdk/aws-lambda-nodejs/lib/builder.ts

This file was deleted.

137 changes: 137 additions & 0 deletions packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import * as lambda from '@aws-cdk/aws-lambda';
import * as cdk from '@aws-cdk/core';
import * as fs from 'fs';
import * as path from 'path';
import { findPkgPath } from './util';

/**
* Options for Parcel bundling
*/
export interface ParcelOptions {
/**
* Entry file
*/
readonly entry: string;

/**
* Expose modules as UMD under this name
*/
readonly global: string;

/**
* Minify
*/
readonly minify?: boolean;

/**
* Include source maps
*/
readonly sourceMaps?: boolean;

/**
* The cache directory
*/
readonly cacheDir?: string;

/**
* The node version to use as target for Babel
*/
readonly nodeVersion: string;

/**
* The docker tag of the node base image to use in the parcel-bundler docker image
*
* @see https://hub.docker.com/_/node/?tab=tags
*/
readonly nodeDockerTag: string;

/**
* The root of the project. This will be used as the source for the volume
* mounted in the Docker container.
*/
readonly projectRoot: string;

/**
* The environment variables to pass to the container running Parcel.
*
* @default - no environment variables are passed to the container
*/
readonly environment?: { [key: string]: string; };
}

/**
* Parcel code
*/
export class Bundling {
public static parcel(options: ParcelOptions): lambda.AssetCode {
// Original package.json path and content
let pkgPath = findPkgPath();
if (!pkgPath) {
throw new Error('Cannot find a `package.json` in this project.');
}
pkgPath = path.join(pkgPath, 'package.json');
const originalPkg = fs.readFileSync(pkgPath);
const originalPkgJson = JSON.parse(originalPkg.toString());

// Update engines.node in package.json to set the right Babel target
setEngines(options.nodeVersion, pkgPath, originalPkgJson);

// Entry file path relative to container path
const containerEntryPath = path.join(cdk.AssetStaging.BUNDLING_INPUT_DIR, path.relative(options.projectRoot, path.resolve(options.entry)));

try {
const command = [
'parcel', 'build', containerEntryPath.replace(/\\/g, '/'), // Always use POSIX paths in the container
'--out-dir', cdk.AssetStaging.BUNDLING_OUTPUT_DIR,
'--out-file', 'index.js',
'--global', options.global,
'--target', 'node',
'--bundle-node-modules',
'--log-level', '2',
!options.minify && '--no-minify',
!options.sourceMaps && '--no-source-maps',
...(options.cacheDir ? ['--cache-dir', '/parcel-cache'] : []),
].filter(Boolean) as string[];

return lambda.Code.fromAsset(options.projectRoot, {
assetHashType: cdk.AssetHashType.BUNDLE,
bundling: {
image: cdk.BundlingDockerImage.fromAsset(path.join(__dirname, '../parcel-bundler'), {
buildArgs: {
NODE_TAG: options.nodeDockerTag ?? `${process.versions.node}-alpine`,
},
}),
environment: options.environment,
volumes: options.cacheDir
? [{ containerPath: '/parcel-cache', hostPath: options.cacheDir }]
: [],
workingDirectory: path.dirname(containerEntryPath).replace(/\\/g, '/'), // Always use POSIX paths in the container
command,
},
});
} finally {
restorePkg(pkgPath, originalPkg);
}
}
}

function setEngines(nodeVersion: string, pkgPath: string, originalPkgJson: any): void {
// Update engines.node (Babel target)
const updateData = {
engines: {
node: `>= ${nodeVersion}`,
},
};

// Write new package.json
if (Object.keys(updateData).length !== 0) {
fs.writeFileSync(pkgPath, JSON.stringify({
...originalPkgJson,
...updateData,
}, null, 2));
}
}

function restorePkg(pkgPath: string, originalPkg: Buffer): void {
fs.writeFileSync(pkgPath, originalPkg);
}
37 changes: 15 additions & 22 deletions packages/@aws-cdk/aws-lambda-nodejs/lib/function.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import * as lambda from '@aws-cdk/aws-lambda';
import * as cdk from '@aws-cdk/core';
import * as crypto from 'crypto';
import * as fs from 'fs';
import * as path from 'path';
import { Builder } from './builder';
import { Bundling } from './bundling';
import { findGitPath, nodeMajorVersion, parseStackTrace } from './util';

/**
Expand Down Expand Up @@ -103,37 +102,31 @@ export class NodejsFunction extends lambda.Function {
}

const entry = findEntry(id, props.entry);
const handler = props.handler || 'handler';
const buildDir = props.buildDir || path.join(path.dirname(entry), '.build');
const handlerDir = path.join(buildDir, crypto.createHash('sha256').update(entry).digest('hex'));
const handler = props.handler ?? 'handler';
const defaultRunTime = nodeMajorVersion() >= 12
? lambda.Runtime.NODEJS_12_X
: lambda.Runtime.NODEJS_10_X;
const runtime = props.runtime || defaultRunTime;
const runtime = props.runtime ?? defaultRunTime;
const projectRoot = props.projectRoot ?? findGitPath();
if (!projectRoot) {
throw new Error('Cannot find project root. Please specify it with `projectRoot`.');
}

// Build with Parcel
const builder = new Builder({
entry,
outDir: handlerDir,
global: handler,
minify: props.minify,
sourceMaps: props.sourceMaps,
cacheDir: props.cacheDir,
nodeVersion: extractVersion(runtime),
nodeDockerTag: props.nodeDockerTag || `${process.versions.node}-alpine`,
projectRoot: path.resolve(projectRoot),
environment: props.containerEnvironment,
});
builder.build();
const nodeDockerTag = props.nodeDockerTag ?? `${process.versions.node}-alpine`;

super(scope, id, {
...props,
runtime,
code: lambda.Code.fromAsset(handlerDir),
code: Bundling.parcel({
entry,
global: handler,
minify: props.minify,
sourceMaps: props.sourceMaps,
cacheDir: props.cacheDir,
nodeVersion: extractVersion(runtime),
nodeDockerTag,
projectRoot: path.resolve(projectRoot),
environment: props.containerEnvironment,
}),
handler: `index.${handler}`,
});
}
Expand Down
Loading

0 comments on commit 5491922

Please sign in to comment.