TypeScript Serverless Project Template
A robust template for building serverless applications using TypeScript, AWS Lambda, and Serverless Framework with esbuild bundling.
Project Structure
lib/
└── helper.ts # Shared utility functions
services/ts-test/
├── serverless.yml # Serverless configuration
├── src/
│ ├── handlers/ # Lambda function handlers
│ │ └── view.ts
│ └── utils/ # Service-specific utilities
│ └── util.ts
└── tsconfig.json # TypeScript configuration
Features
- TypeScript support with strict type checking
- Serverless Framework for easy AWS Lambda deployments
- esbuild for fast bundle compilation
- Shared library support across multiple services
- Local development with serverless-offline
- Source maps for better debugging
- CORS support out of the box
Prerequisites
- Node.js (v18.x or later)
- AWS CLI configured with appropriate credentials
- Serverless Framework CLI (
npm install -g serverless)
Quick Start
- Clone this template:
git clone https://7EDGEx@dev.azure.com/7EDGEx/Backend/_git/Backend
- Install dependencies:
cd serverless-typescript/
npm install
cd services/ts-test
- Run locally:
serverless offline
- Deploy:
# Deploy to dev stage (default)
serverless deploy
# Deploy to specific stage
serverless deploy --stage dev
Install Serverless plugins and esbuild (if not exists in package.json)
npm install --save-dev serverless-esbuild esbuild serverless-offline
Configuration
TypeScript Configuration (tsconfig.json)
The project uses a TypeScript configuration optimized for AWS Lambda:
(customize based on your requirements)
{
"compilerOptions": {
"preserveConstEnums": true,
"strictNullChecks": true,
"sourceMap": true,
"allowJs": true,
"target": "es2020",
"module": "commonjs",
"moduleResolution": "node",
"outDir": ".build",
"rootDir": "./",
"baseUrl": "./",
"paths": {
"@lib/*": ["../../lib/*"]
}
},
"include": [
"src/**/*.ts",
"lib/**/*.ts"
],
"exclude": [
"node_modules"
]
}
Key features:
- Path aliases for shared library imports (
@lib/*) - Source map generation for debugging
- Strict null checks for better type safety
- ES2020 target for modern Node.js features
Serverless Configuration (serverless.yml)
service: ts-test
provider:
name: aws
runtime: nodejs20.x
region: ap-south-1
functions:
view:
handler: src/handlers/view.handler
events:
- http:
path: /
method: get
cors: true
plugins:
- serverless-esbuild
- serverless-offline
custom:
esbuild:
bundle: true
minify: false
sourcemap: true
target: "node20"
platform: "node"
concurrency: 10
Key features:
- esbuild configuration for optimal bundling
- CORS enabled by default
- Environment variables support
- Local development support
Handler Example
Here’s an example of a typical Lambda handler with TypeScript:
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
import { headers } from '@lib/helper';
export const handler = async (
event: APIGatewayProxyEvent
): Promise<APIGatewayProxyResult> => {
return {
statusCode: 200,
headers,
body: JSON.stringify({
message: 'Success',
data: headers,
}),
};
};
Shared Library Usage
The project supports a shared library pattern. Example usage:
// In lib/helper.ts
export const headers: Record<string, string> = {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': 'true',
};
// In your handler
import { headers } from '@lib/helper';
Development Workflow
Local Development
Start the local development server:
cd services/ts-test
serverless offline
This will:
- Start a local API Gateway emulator
- Enable automatic rebuilding on file changes
- Provide local endpoints for testing
- Watch for file changes (with esbuild watch mode)
Deployment
Deploy to AWS (from within the service directory):
# Deploy to dev stage
serverless deploy
# Deploy to specific stage
serverless deploy --stage production
# Deploy a single function
serverless deploy function -f functionName
Package Only (No Deployment)
Create deployment package without deploying:
serverless package
Testing Functions Locally
Test specific functions locally:
serverless invoke local -f functionName
esbuild Configuration
The project uses serverless-esbuild plugin with optimized settings:
custom:
esbuild:
bundle: true # Bundles all dependencies
minify: false # Keeps code readable
sourcemap: true # Enables debugging
target: "node20" # Optimizes for Node.js 20
platform: "node" # Targets Node.js platform
concurrency: 10 # Parallel bundling
Git Ignore
sample .gitignore for ignoring .map and build files
# Ignore built JavaScript files in specific directories
serverless-typescript/services/**/lib/**/*.js
serverless-typescript/services/**/lib/**/*.js.map
serverless-typescript/lib/**/*.js
serverless-typescript/lib/**/*.js.map
# Ignore the entire .build directory
.build/
Additional esbuild features available:
- Custom plugins support
- External dependency management
- Watch mode for development
- Customizable build options
Best Practices
-
Type Safety
- Use strict TypeScript configurations
- Define interfaces for all data structures
- Utilize AWS Lambda types
-
Code Organization
- Keep handlers focused on routing logic
- Move business logic to separate services
- Share common code through the lib directory
-
Error Handling
- Implement proper error boundaries
- Use typed error responses
- Include appropriate HTTP status codes
-
Testing
- Write unit tests for business logic
- Use integration tests for API endpoints
- Test locally before deployment
Troubleshooting
Common issues and solutions:
-
Path Resolution Issues
# Ensure you're in the correct service directory cd services/ts-test # Check tsconfig.json paths configuration -
Build Errors
# Clear esbuild cache rm -rf .esbuild # Try deploying again serverless deploy -
Deployment Failures
- Verify AWS credentials
- Check CloudWatch logs
- Ensure proper IAM permissions
- Run
serverless printto check the final configuration
-
Local Development Issues
# Start with debugging serverless offline --verbose # Or with specific stage serverless offline --stage dev