-
-
Notifications
You must be signed in to change notification settings - Fork 48
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 Node v14.x #25
base: master
Are you sure you want to change the base?
Conversation
Awesome – thanks for giving this a shot – I was just gonna wait until official support TBH 😆 Might just be worth adding a top-level await statement to test/index.js to make sure that works – would be a nice-to-have |
Hey @mhart ! Loving the quick response! I would totally wait if I could but its one of those situations 😞 it was this or transpiling 🤮 (IMHO) I added a top-level await ✅ works like a charm 🍀 |
Ok, so I've had a play – the main problem is this doesn't work out of the box with CommonJS modules – so it's not straightforward for people to just upgrade their existing Lambda functions. I have no idea if something like this would work or not – I haven't played around enough with mixing ESM and CommonJS: import { createRequire } from 'module'
global.require = createRequire(import.meta.url) The other option would be to have an env var that toggles this behavior |
Based on my experience it will have to be one way or another during the build because of the |
Basically, if we can get it to work with I'm just not sure whether we should try for both out-of-the-box, or just ESM out-of-the-box with CommonJS support behind an env var, or CommonJS out-of-the-box and ESM behind an env var. |
based on Node docs
I'd say I set this up backwards. By default we should support CommonJS modules and allow for a flag to opt into ES6 modules. We might be able to handle an env var in the bootstrap and use the |
Yeah, I think that sounds right – I think it's better by default to assume traditional CommonJS modules |
I haven't dived in yet, but for some reason this is noticeably slower to init than v12.x – which I suspect would also reflect in Lambda itself. Any idea why that might be? Just the overhead of |
(that's why you see all the pings btw – because it takes so long to init – they ping every 100ms so usually you don't see them) |
I did add that 1 second sleep to the test file as the top-level await test. Not sure if thats where your noticing the performance? |
Haha, lol – yeah, that'd be it – didn't even think of it |
Ok, r&d complete. Dynamic es6 modules | commonjs modules switching is not available in any workable way for our use case. I can think of some hacks but they involve eval or adding more scripts -- all bad things for performance and security. You may want to dig in a little yourself to validate this but my suggestion is we break the
then provide commonjs|modules specific layers. |
Oh, we can't just do it behind a flag? Like, either |
After some more work I am happy to eat my words and say.... it works 🥳 A few updates in the last commit
|
I published this in my aws account, based a lambda on it, and did a little testing ✅ |
I know this issue is a bit outside the scope here, but I ran into it using your image and wanted to get another opinion. Commonjs relies on the Thanks for the hard work putting together this runtime. |
Oh my page was open and didn't see you got it working! Yay! |
added custom loader hook to resolve /opt/nodejs/ modules
I don't love it... I don't like it... haha the warning on that All that is probably already understood by everyone. I'm on the fence. Another concern is performance. If I understand the way its written, it will always try to pull every required import from |
I agree with the node on performance. I think I did the priority backwards and it should try to load from the current path first, then /opt. That should mitigate any performance hit, but import errors might look a little weird. (unless i were to save the original error and throw it if any others aren't found) I completely understand the hesitancy to use the Will update with pull request in a bit. |
For sure. I'm actually a big fan of this solution aside from experimental state. If the api were stable I'd be thrilled. A few line custom loader is pretty slick. I was thinking maybe we put this behind an opt in flag as well but I'm not sure it would really matter (that is If you switch the try order so it tries the default first). If you try to import a module and its not available your lambda is erroring out anyway -- whats another few ms to check Someone could also have some |
@rayepps made another pr. Changed the order of precedence and added the missing paths. Any modules resolved with the default resolution should take no performance hit now. I'm happy calling it complete now. Note: I wanted to try to do some new async resolution but the defaultResolve function is synchronous so i couldn't |
added missing resolution paths and changed order or precedence
@brandonryan is the loader stuff only an issue if ESM is used? If so, we could just leave the experimental stuff up to the NODE_OPTIONS env var if ppl wanted to use it. ie, they can set NODE_OPTIONS env var on their Lambda to something like:
|
I feel like the best way to provide backwards compat is to default everything here to be in CommonJS – ie, bootstrap.js uses requires, etc. Then We can just use We could also explore whether it's worth auto-guessing based on file extension |
@mhart the
Using
That being said, im not the maintainer of the repo, so use your own discretion. As a side note, I just now thought it might be a good idea to read Currently everything does default to commonjs. |
My issues with adding the experimental flag by default for ESM modules is that 1) it's experimental and 2) it could add time to the loader – for every import statement. If you've got a Lambda doing hundreds of imports, that could have quite an impact.
What do you mean by this? |
Im good with that reasoning. Since it tries to load from the default loader first it shouldn't be that big of a performance hit, but I understand the reservation. I meant that most official lambda runtimes are configured to support importing packages from /opt as the default, and not supporting that out-of-the-box would be breaking convention. |
@brandonryan yeah, that's a fair point. Would be nice if everything "just worked". Maybe the impact wouldn't be that bad. We could make it an opt-out deal perhaps. |
I'll make some more updates soon with your suggestions. Working my day job right now so it'll be a few hours. |
@rayepps Side note: I'm going to make another issue for this, but for some reason errors aren't reporting in the lambda console correctly. |
removed loader type flag in favor of auto resolution
@mhart pull request updated. I didnt add the c code to add an opt out flag because im not experienced enough in c to confidently do that. |
Hi, I wonder if there's any update on this PR? It would be great if lambda 14.x is supported! |
I've suggested some improvements regarding this PR: |
Hi @mhart, would it be possible to get this PR sorted? I've got a local test stack which depends on the lambci nodejs12 docker image but we want to update to nodejs14 and this is the only thing holding it back. |
@matthewhaywardmsm can you be more specific about how this layer affects your test stack? |
We need to be able to run multiple lambdas locally (as part of a local implementation of AWS Cognito which has multiple lambdas), and the way we've done it is to use the lambci/lambda:nodejs12.x docker image as a base image for each of them. We want to update to nodejs14, but currently there is no version 14 available of lambda:nodejs12.x base image. This layer appears to be a custom prerequisite to building the lambda:nodejs12.x image, so I thought this would need updating in order to make nodejs14 buildable in lambci/lambda. |
@matthewhaywardmsm I think you might be looking at the wrong repos. You probably want lambci/docker-lambda#329 |
Thanks @mhart, I ended up using amazon/aws-lambda-nodejs:14 as a base image instead. |
Thank you @rayepps for posting this PR, and @mhart for creating this project. export LAYER_NAME=nodejs16
export NODE_VERSION=16.20.0 |
The changes from v12.x to v14.x are very small. All I really did was
module
typemodule
typeOn my machine:
✅ build.sh completes and produces expected
layer.zip
✅ test.sh completes and outputs expected log lines
🟨 publish.sh -- obviously I can't do this
🟨 check.sh -- obviously depends on ^^^