How to use esbuild to transpile and bundle your TypeScript Lambda functions in a Serverless Framework project - all without using any plugins!
Example source code from article Using esbuild in your Serverless Framework Project.
How to use esbuild to transpile and bundle your TypeScript Lambda functions in a Serverless Framework project - all without using any plugins!
Example source code from article Using esbuild in your Serverless Framework Project.
const fs = require('fs') | |
const cloudformationSchema = require('@serverless/utils/cloudformation-schema') | |
const esbuild = require('esbuild') | |
const yaml = require('js-yaml') | |
const rimraf = require('rimraf') | |
const SERVERLESS_YML_PATH = './serverless.yml' | |
const OUT_DIR = './dist' | |
// ref: https://esbuild.github.io/api/#simple-options | |
const ESBUILD_CONFIG = { | |
bundle: true, | |
external: ['aws-sdk'], | |
format: 'cjs', | |
minify: true, | |
platform: 'node', | |
outbase: 'src', | |
outdir: OUT_DIR, | |
} | |
async function getConfig() { | |
return yaml.loadAll(fs.readFileSync(SERVERLESS_YML_PATH), { | |
schema: cloudformationSchema, | |
})[0] | |
} | |
;(async function main() { | |
rimraf.sync(OUT_DIR) | |
const { functions, provider } = await getConfig() | |
const handlers = Object.entries(functions) | |
.map(([, fn]) => fn.handler.replace('dist/', 'src/')) | |
.map((fn) => { | |
const parts = fn.split('.') | |
const path = parts.slice(0, parts.length - 1).join('.') | |
return fs.existsSync(path + '.ts') ? path + '.ts' : path + '.js' | |
}) | |
console.info('Building handlers..') | |
await esbuild | |
.build({ | |
...ESBUILD_CONFIG, | |
entryPoints: handlers, | |
target: provider.runtime | |
? 'node' + provider.runtime.match(/\d+/g)[0] | |
: 'node14', | |
}) | |
.catch(() => process.exit(1)) | |
handlers.map((handler) => { | |
const bundlePath = handler.replace('.ts', '.js').replace('src/', 'dist/') | |
const stat = fs.statSync(bundlePath) | |
console.log( | |
bundlePath, | |
'-', | |
+(stat.size / 1024 / 1024).toPrecision(3), | |
'MB', | |
) | |
}) | |
})() |
{ | |
"name": "example", | |
"scripts": { | |
"build": "node build.js", | |
"predeploy": "npm run build", | |
"deploy": "serverless deploy" | |
}, | |
"devDependencies": { | |
"@types/aws-lambda": "8.10.83", | |
"esbuild": "0.12.22", | |
"js-yaml": "4.1.0", | |
"serverless": "2.55.0", | |
"rimraf": "3.0.2", | |
"typescript": "4.3.5" | |
} | |
} |
service: example | |
provider: | |
name: aws | |
runtime: nodejs14.x | |
package: | |
excludeDevDependencies: false | |
patterns: | |
- '!./**' | |
- './dist/**' | |
functions: | |
example: | |
description: An example lambda function | |
handler: dist/example.handler | |
memorySize: 256 | |
events: | |
- http: GET /example |
// Save as: src/example.ts | |
import * as AWSLambda from 'aws-lambda' | |
export default async function exampleHandler( | |
event: AWSLambda.APIGatewayProxyEvent, | |
context: AWSLambda.Context, | |
): Promise<AWSLambda.APIGatewayProxyStructuredResultV2> { | |
return { | |
statusCode: 200, | |
body: JSON.stringify({ event, context }), | |
} | |
} |