Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Cloudfront Functions #102

Open
mrgrain opened this issue Oct 8, 2021 · 16 comments
Open

Support for Cloudfront Functions #102

mrgrain opened this issue Oct 8, 2021 · 16 comments
Labels
backlog enhancement New feature or request help wanted Extra attention is needed

Comments

@mrgrain
Copy link
Owner

mrgrain commented Oct 8, 2021

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.

@moltar
Copy link

moltar commented Oct 9, 2021

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

@mrgrain
Copy link
Owner Author

mrgrain commented Oct 9, 2021

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. 🤔

@moltar
Copy link

moltar commented Oct 9, 2021

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.

@mrgrain mrgrain added the enhancement New feature or request label Oct 17, 2021
@github-actions
Copy link

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.

@github-actions github-actions bot added the stale label Dec 17, 2021
@mrgrain mrgrain removed the stale label Dec 17, 2021
@github-actions
Copy link

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.

@github-actions github-actions bot added the stale label Feb 16, 2022
@mrgrain mrgrain added backlog and removed stale labels Feb 16, 2022
@mrgrain
Copy link
Owner Author

mrgrain commented Mar 14, 2022

Cloudfront Functions requires ES5 which esbuild cannot target right now.
See: evanw/esbuild#297

@gunta
Copy link

gunta commented May 24, 2022

Definitely having eslint rules for Cloudfront Functions would be amazing

@mrgrain mrgrain added this to Roadmap Aug 7, 2022
@mrgrain mrgrain moved this to Todo in Roadmap Aug 7, 2022
@mrgrain mrgrain added the help wanted Extra attention is needed label Aug 11, 2022
@blimmer
Copy link

blimmer commented Sep 15, 2023

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!

@mrgrain
Copy link
Owner Author

mrgrain commented Sep 16, 2023

Cool, than you! I might pull this config out into a Cloudfront Function Construct.

@blimmer
Copy link

blimmer commented Sep 17, 2023

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.

@moltar
Copy link

moltar commented Sep 17, 2023

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?

@mrgrain
Copy link
Owner Author

mrgrain commented Sep 17, 2023

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).

@blimmer
Copy link

blimmer commented May 10, 2024

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

@moltar
Copy link

moltar commented May 10, 2024

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

@moltar
Copy link

moltar commented Jul 2, 2024

Found this today, but did not try yet: https://www.npmjs.com/package/esbuild-cf-functions-plugin

@mrgrain
Copy link
Owner Author

mrgrain commented Jul 2, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backlog enhancement New feature or request help wanted Extra attention is needed
Projects
Status: Todo
Development

No branches or pull requests

4 participants