cdk-esbuild
cdk-esbuild copied to clipboard
Support for Cloudfront Functions
Cloudfront supports small inline JavaScript functions. They have some limitations, mainly regarding size and used memory.
We should evaluate if the existing inline code works with it, or add support and document the usage.
They have some peculiar limitations.
Docs: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/functions-javascript-runtime-features.html
The CloudFront Functions JavaScript runtime environment is compliant with ECMAScript (ES) version 5.1 and also supports some features of ES versions 6 through 9. It also provides some nonstandard methods that are not part of the ES specifications. The following topics list all the supported language features.
The const and let statements are not supported.
Restricted features: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/functions-javascript-runtime-features.html#writing-functions-javascript-features-restricted-features
- Dynamic code evaluation
- Timers
- Date and timestamps
- File system access
- Network access
Interesting! Thanks for the reading links. I guess with esbuild we would be able to set the compile target to es5
. The other limitations will be harder to enforce, and probably have to be left to the user to ensure compatibility. 🤔
The other limitations will be harder to enforce, and probably have to be left to the user to ensure compatibility.
Would probably be a lot of work, and difficult to configure, but maybe eslint rules?
Probably outside the scope of this package though.
This issue is now marked as stale because it hasn't seen activity for a while. Add a comment or it will be closed soon.
This issue is now marked as stale because it hasn't seen activity for a while. Add a comment or it will be closed soon. If you wish to exclude this issue from being marked as stale, add the "backlog" label.
Cloudfront Functions requires ES5 which esbuild cannot target right now. See: https://github.com/evanw/esbuild/issues/297
Definitely having eslint rules for Cloudfront Functions would be amazing
I've actually had decent luck with this esbuild
config:
build({
entryPoints: [join(cloudFrontFunction, "src", "index.ts")],
outdir: join(cloudFrontFunction, "dist"),
// Make compatible with CloudFront Functions limited ES5 JavaScript runtime
// https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/functions-javascript-runtime-features.html#writing-functions-javascript-features-core
format: "cjs",
target: "es5",
platform: "neutral",
treeShaking: true,
banner: {
js: "var module = {};", // allows exporting functions from TS files to unit test
},
minifyIdentifiers: false,
supported: {
"const-and-let": false, // throws a build-time error if you use `const` or `let`, but at least warns you
"exponent-operator": true,
"template-literal": true,
arrow: true,
"rest-argument": true,
"regexp-named-capture-groups": true,
},
});
It definitely doesn't transpile everything, but it works pretty well!
Cool, than you! I might pull this config out into a Cloudfront Function Construct.
Sounds good - I'd be happy to collab on that PR if it would be helpful. For me, it has been great to write my CloudFront functions in TS, write tests in jest
, and then deploy the ES5-ish compatible version to AWS.
There are some intricacies we'd probably need to document. For instance, with the config I posted and this very simple example:
import type { CloudFrontFunctionsEvent } from "aws-lambda";
export function handler(event: CloudFrontFunctionsEvent) {
const request = event.request;
return request;
}
You get this error:
✘ [ERROR] Transforming const to the configured target environment ("es5" + 6 overrides) is not supported yet
src/stacks/cloudfront-functions/content-preview/src/index.ts:4:2:
4 │ const request = event.request;
╵ ~~~~~
/Users/blimmer/code/company/stacks/node_modules/esbuild/lib/main.js:1650
let error = new Error(text);
^
Error: Build failed with 1 error:
src/stacks/cloudfront-functions/content-preview/src/index.ts:4:2: ERROR: Transforming const to the configured target environment ("es5" + 6 overrides) is not supported yet
at failureErrorWithLog (/Users/blimmer/code/company/stacks/node_modules/esbuild/lib/main.js:1650:15)
at /Users/blimmer/code/company/stacks/node_modules/esbuild/lib/main.js:1059:25
at /Users/blimmer/code/company/stacks/node_modules/esbuild/lib/main.js:1004:52
at buildResponseToResult (/Users/blimmer/code/company/stacks/node_modules/esbuild/lib/main.js:1057:7)
at /Users/blimmer/code/company/stacks/node_modules/esbuild/lib/main.js:1086:16
at responseCallbacks.<computed> (/Users/blimmer/code/company/stacks/node_modules/esbuild/lib/main.js:703:9)
at handleIncomingPacket (/Users/blimmer/code/company/stacks/node_modules/esbuild/lib/main.js:763:9)
at Socket.readFromStdout (/Users/blimmer/code/company/stacks/node_modules/esbuild/lib/main.js:679:7)
at Socket.emit (node:events:514:28)
at addChunk (node:internal/streams/readable:324:12) {
errors: [Getter/Setter],
warnings: [Getter/Setter]
}
Node.js v18.17.1
so you have to write:
import type { CloudFrontFunctionsEvent } from "aws-lambda";
export function handler(event: CloudFrontFunctionsEvent) {
var request = event.request;
return request;
}
which is surprising.
Also, writing console.info
anywhere doesn't throw an esbuild
error, so you wouldn't find out about issues until runtime. So, the experience isn't killer, but it's better than nothing.
Also, writing console.info anywhere doesn't throw an esbuild error, so you wouldn't find out about issues until runtime. So, the experience isn't killer, but it's better than nothing.
Maybe it'd be possible to achieve this via esbuild plugins?
Or ESLint rules?
Disabling features in esbuild and causing a build failure seems like the earliest possible point that fits the remit of this construct.
Ideally, we would have eslint rules and plugins available. Maybe a types package that is used instead of @types/node
would help as well. If any of these come about, I'd be happy to include it here however it makes sense (code or docs).
I wonder if this is as relevant anymore now that runtime 2.0 is out: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/functions-javascript-runtime-20.html
There are still many restricted features: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/functions-javascript-runtime-20.html#writing-functions-javascript-features-restricted-features-20
Found this today, but did not try yet: https://www.npmjs.com/package/esbuild-cf-functions-plugin
Nice find! Using a plugin is going to be annoying, but the settings might be easy enough to adapt. Although from looking at the source, it seems to do fairly basic stuff.