Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ serverless deploy
| [AWS API Gateway Custom Authorizer Function with Auth0 example in NodeJS](https://github.com/serverless/examples/tree/v4/aws-node-auth0-custom-authorizers-api) <br/> This is an example of how to protect API endpoints with Auth0, JSON Web Tokens (jwt) and a custom authorizer lambda function. | nodeJS |
| [Dynamic Image Resizing API](https://github.com/serverless/examples/tree/v4/aws-node-dynamic-image-resizer) <br/> This example shows you how to setup a dynamic image resizer API | nodeJS |
| [DynamoDB Streams Processing to S3](https://github.com/serverless/examples/tree/v4/aws-node-dynamodb-stream-processing) <br/> This example shows you how to consume a DynamoDB Stream, transform records, and archive them to S3. | nodeJS |
| [AWS Node.js ES Module Bundles with esbuild](https://github.com/serverless/examples/tree/v4/aws-node-esm-esbuild) <br/> This example demonstrates how to bundle TypeScript handlers as ES modules (.mjs) with the built-in esbuild support, without adding a package.json to the deployment artifact. | nodeJS |
| [AWS Storing Encrypted Secrets example in NodeJS](https://github.com/serverless/examples/tree/v4/aws-node-env-variables-encrypted-in-a-file) <br/> This example demonstrates how to store secrets like API keys encrypted in your repository while providing them as environment variables to your AWS Lambda functions. | nodeJS |
| [AWS Serverless Environment Variables Usage example in NodeJS](https://github.com/serverless/examples/tree/v4/aws-node-env-variables) <br/> This example demonstrates how to use environment variables for AWS Lambdas. | nodeJS |
| [Node Express API on AWS](https://github.com/serverless/examples/tree/v4/aws-node-express-api) <br/> This template demonstrates how to develop and deploy a simple Node Express API running on AWS Lambda using the Serverless Framework. | nodeJS |
Expand Down
70 changes: 70 additions & 0 deletions aws-node-esm-esbuild/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<!--
title: 'AWS Node.js ES Module Bundles with esbuild'
description: 'This example demonstrates how to bundle TypeScript handlers as ES modules (.mjs) with the built-in esbuild support, without adding a package.json to the deployment artifact.'
layout: Doc
framework: v4
platform: AWS
language: nodeJS
authorLink: 'https://github.com/serverless'
authorName: 'Serverless, Inc.'
authorAvatar: 'https://avatars1.githubusercontent.com/u/13742415?s=200&v=4'
-->

# AWS Node.js ES Module Bundles with esbuild

This example demonstrates how to bundle a TypeScript handler as an ES module using the Serverless Framework's built-in esbuild support. The `outExtension` option emits the bundle as `.mjs`, which makes the Lambda Node.js runtime load it with the ESM loader — no `package.json` with `"type": "module"` needs to be shipped inside the deployment artifact.

```yaml
build:
esbuild:
format: esm
outExtension:
'.js': '.mjs'
```

The handler proves it runs as an ES module by reading `import.meta.url`, which is only available in ESM. Function `handler` values stay unchanged — Lambda resolves the handler file extension automatically.

This is useful when:

- You want ES module semantics on Lambda (for example top-level `await` for initialization) with a CommonJS or extension-less project setup, such as a monorepo where the root `package.json` cannot declare `"type": "module"`.
- You want the deployment artifact to contain nothing but the bundled handler files.

Both `format` and `outExtension` can also be returned from a `configFile` JavaScript configuration — see the [building documentation](https://www.serverless.com/framework/docs/providers/aws/guide/building) for all esbuild options.

## Usage

### Deploy

```bash
serverless deploy
```

### Invoke

After deployment, call the HTTP endpoint printed in the deploy output:

```bash
curl https://xxxxxxx.execute-api.us-east-1.amazonaws.com/time
```

Which should respond with:

```json
{
"message": "Hello from a handler loaded as an ES module!",
"time": "2026-07-24T12:00:00.000Z"
}
```

You can also invoke the function directly, locally or remotely:

```bash
serverless invoke local -f time
serverless invoke -f time
```

### Clean up

```bash
serverless remove
```
24 changes: 24 additions & 0 deletions aws-node-esm-esbuild/serverless.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
service: aws-node-esm-esbuild
frameworkVersion: '4'

provider:
name: aws
runtime: nodejs24.x
architecture: arm64

build:
esbuild:
# Emit the bundled handlers as ES modules. The .mjs extension makes the
# Lambda Node.js runtime load them with the ESM loader, without shipping a
# package.json with "type": "module" inside the deployment artifact.
format: esm
outExtension:
'.js': '.mjs'

functions:
time:
handler: src/handler.currentTime
events:
- httpApi:
path: /time
method: get
12 changes: 12 additions & 0 deletions aws-node-esm-esbuild/src/handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Bundled by esbuild to .serverless/build/src/handler.mjs and loaded by the
// Lambda runtime as an ES module — import.meta is only available in ESM.
const loadedAs = import.meta.url.endsWith('.mjs') ? 'ES module' : 'CommonJS'

export const currentTime = async () => ({
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
message: `Hello from a handler loaded as an ${loadedAs}!`,
time: new Date().toISOString(),
}),
})
2 changes: 1 addition & 1 deletion aws-node-http-api-typescript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ framework: v4
platform: AWS
language: nodeJS
authorLink: 'https://github.com/serverless'
authorName: 'Serverless, inc.'
authorName: 'Serverless, Inc.'
authorAvatar: 'https://avatars1.githubusercontent.com/u/13742415?s=200&v=4'
-->

Expand Down
2 changes: 1 addition & 1 deletion aws-node-rest-api-typescript-simple/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ platform: AWS
language: nodeJS
priority: 10
authorLink: 'https://github.com/serverless'
authorName: 'Serverless, inc.'
authorName: 'Serverless, Inc.'
authorAvatar: 'https://avatars1.githubusercontent.com/u/13742415?s=200&v=4'
-->

Expand Down
2 changes: 1 addition & 1 deletion aws-python-rest-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ platform: AWS
language: python
priority: 2
authorLink: 'https://github.com/serverless'
authorName: 'Serverless, inc.'
authorName: 'Serverless, Inc.'
authorAvatar: 'https://avatars1.githubusercontent.com/u/13742415?s=200&v=4'
-->

Expand Down
2 changes: 1 addition & 1 deletion aws-python-sqs-worker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ platform: AWS
language: Python
priority: 2
authorLink: 'https://github.com/serverless'
authorName: 'Serverless, inc.'
authorName: 'Serverless, Inc.'
authorAvatar: 'https://avatars1.githubusercontent.com/u/13742415?s=200&v=4'
-->

Expand Down
2 changes: 1 addition & 1 deletion aws-ruby-sinatra-dynamodb-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ platform: AWS
language: Ruby
priority: 5
authorLink: 'https://github.com/serverless'
authorName: 'Serverless, inc.'
authorName: 'Serverless, Inc.'
authorAvatar: 'https://avatars1.githubusercontent.com/u/13742415?s=200&v=4'
-->

Expand Down
Loading