AWS CloudFront Functions are a powerful tool for running lightweight JavaScript code at the edge, allowing you to manipulate requests and responses.
However, AWS requires these functions to be written in Vanilla JavaScript, which can be limiting for developers who prefer TypeScript’s type safety and modern syntax.
In this article, I’ll walk you through a solution to write CloudFront Functions in TypeScript, import additional files, and test them effectively.
Challenge
CloudFront Functions must be written in ES5 JavaScript, which lacks the modern features and type safety of TypeScript. This requirement poses a challenge for developers who want to leverage TypeScript’s benefits while still deploying to CloudFront.
Solution
The solution involves using TypeScript to write your CloudFront Functions and then transpiling them to ES5 JavaScript. This approach allows you to maintain the benefits of TypeScript during development and testing, while still meeting AWS’s requirements for deployment.
Key Components
TypeScript Compiler Options:
- Configure the TypeScript compiler to target ES5 and remove module syntax, as CloudFront’s JavaScript environment doesn’t support all CommonJS runtime modules.
- Custom Transformers: Use custom TypeScript transformers to remove export keywords and __esModule properties, ensuring the output is compatible with CloudFront.
- Build Script: Create a build script to transpile TypeScript files to JavaScript, applying the custom transformers.
- Testing: Write unit tests for your TypeScript code using a testing framework like Jest, ensuring your logic is sound before deployment.
Implementation
Below is a simplified example of how you might set up your TypeScript project for CloudFront Functions:
TypeScript Configuration (tsconfig.json)
{
"compilerOptions": {
"target": "es5", // MUST BE ES5 for CloudFront Function support https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/functions-javascript-runtime-features.html#writing-functions-javascript-features-core
"module": "commonjs", // Beware CloudFront JS environment doesn't contain all commonjs runtime modules
"lib": ["es5"],
"strict": true,
"removeComments": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
Custom Transformer
Create a custom transformer to remove export keywords:
import * as ts from 'typescript';
export const removeExportTransformer: ts.TransformerFactory<ts.SourceFile> = (context) => {
return (sourceFile) => {
const visitor: ts.Visitor = (node) => {
if (ts.isModifier(node) && node.kind === ts.SyntaxKind.ExportKeyword) {
return undefined;
}
return ts.visitEachChild(node, visitor, context);
};
return ts.visitNode(sourceFile, visitor);
};
};
Build Script
A script to transpile TypeScript files:
import * as ts from 'typescript';
import * as fs from 'fs';
import * as path from 'path';
import { removeExportTransformer } from './removeExportTransformer';
const compilerOptions: ts.CompilerOptions = {
module: ts.ModuleKind.None,
target: ts.ScriptTarget.ES5,
strict: true,
removeComments: true,
lib: ['es5'],
};
function transpileFile(filePath: string) {
const source = fs.readFileSync(filePath, 'utf-8');
const result = ts.transpileModule(source, {
compilerOptions,
transformers: { before: [removeExportTransformer] },
});
const outputFilePath = filePath.replace('.ts', '.js');
fs.writeFileSync(outputFilePath, result.outputText);
}
const files = fs.readdirSync('./src').filter(file => file.endsWith('.ts'));
files.forEach(file => transpileFile(path.join('./src', file)));
Usage
Build your CloudFront Typescript function before deployment:
ts-node scripts/build-cloudfront.ts
Define the path to your function build output:
const function= new aws_cloudfront.Function(stack, 'CloudfrontFunctionId', {
functionName: 'cloudfront_function',
code: aws_cloudfront.FunctionCode.fromFile({
filePath: `dist/cloudfrontFunction.js`,
}),
runtime: aws_cloudfront.FunctionRuntime.JS_2_0,
})
Testing with Jest
Set up Jest to test your TypeScript code:
module.exports = {
testEnvironment: 'node',
transform: {
'^.+\\.tsx?$': 'ts-jest',
},
testMatch: ['**/__tests__/**/*.ts'],
};
Conclusion
By leveraging TypeScript and custom transformers, you can write, test, and deploy CloudFront Functions with modern JavaScript features and type safety benefits. This approach not only enhances your development experience but also ensures your code is robust and maintainable.
Full working code example you can find on my GitHub
Acknowledgements
Special thanks to the authors of the typescript-remove-exports package, which inspired the custom transformer approach used in this solution. Their work provided a foundation for adapting TypeScript code to meet CloudFront’s requirements.
Top comments (0)