-
Notifications
You must be signed in to change notification settings - Fork 27.4k
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 AWS Lambda as target serverless #6173
Comments
You shouldn't override the serverless loader, instead write a utility that wraps the build output, the point of the serverless target, as documented is provide the low level rendering API so that it can be wrapped for other platforms. Note that the Next.js serverless build isn't particular to Now 2.0, Now 2.0 wraps the |
Eg like the example I posted here: #6070 (comment) |
Thank you for the fast answer. Alright, I understand the API design but having to create a file with a wrapper function for every pages is redundant or having one file as handler for everything is going against the way of using lambdas. On my side, it's a big +1 for an utility / api for handling this wrapping with Next.js directly and I'll be happy to help by working on that. But like you said, I'm not sure this is the scope of Next.js for now. In the meantime I'll stick to my solution as part of my build phase in less hackish way. ✌️ |
As a starter point, you can push your PR. |
As a reference point for others, our AWS Lambda deployment via const express = require("express");
const serverless = require("serverless-http");
const isProduction = process.env.NODE_ENV === "production";
// setup Express and hook up Next.js handler
const app = express();
const getPage = page => require(`./.next/serverless/pages/${page}`).render;
app.get("/", getPage("index"));
app.get("/pageA", getPage("pageA"));
app.get("/pageB", getPage("pageB"));
// for local development (serverless offline)
if (!isProduction) {
// host the static files
app.use("/_next/static", express.static("./.next/static"));
app.use("/static", express.static("./static"));
}
// 404 handler
app.get("*", require("./.next/serverless/pages/_error").render);
// export the wrapped handler for the Lambda runtime
exports.handler = serverless(app); We then copy the static files to S3 (using I'm aware that the page runtimes can also be deployed on a per route basis as separate functions, but we're a bit concerned to do that right now due to us having had bad experiences with Lambda coldstarts in the past. Nonetheless it would be great if someone built an automagic tool specifically for AWS Lambda. That could be a tool that automatically loads the page runtimes from the filesystem (like the script above), or automatically configures serverless to add appropriate routes to each page runtime wrapped up with an HTTP server each. I'm not sure whether |
This comment has been minimized.
This comment has been minimized.
Good point. A single "heavy" Lambda is kept warm more easily though (e.g. through Cloudwatch Events from a Schedule Expressions). But I do see the issue if traffic scales up and we need more Lambdas around than we keep warm. Edit: But I do get that, if cold starts are not an issue because the Lambda bootstraps within tens to hundreds of milliseconds, keeping warm is not a priority at all. |
@beheh thanks for the example above!
thanks! UPD: and here is the answer, with subfolders support:
|
Hi 👋 I've been working on a plugin (https://github.com/danielcondemarin/serverless-nextjs-plugin) for the serverless framework that targets nextjs 8 serverless mode. It adds the compat layer between the AWS Lambdas and the Nextjs page handlers at build time and takes care of uploading the static assets to S3. Seems promising so far, but is still a WIP and haven't been able to test it in anger. |
Hi @danielcondemarin ! There is definitely a niche for plugin like this! I can give it a try over the coming days or weekend and provide a more meaningful feedback, but two things come to my mind as I looked through it:
WDYT? |
@krajowski Thanks for your feedback! |
You'll want to use build time |
Neat, I wasn't aware of this option, found it documented here. That's great because it should mean that the serverless page bundles get the env. bundled in. so there is really nothing to do for the plugin I'm working on. Will test this later 👍 |
Exactly! |
@krajowski I started looking into dynamically deploying the pages via the serverless plugin, tracking the progress here |
@danielcondemarin could you send me a dm on twitter.com/timneutkens / spectrum.chat/users/timneutkens |
@beheh Thanks for sharing your code example! I'm trying to adopt your approach and wonder how do you not need binding
|
@bausk Take a look at https://github.com/zeit/next.js/#cdn-support-with-asset-prefix! We intentionally exclude them from the Lambda zip and push the static assets to S3 instead. |
Excellent, thanks a lot! |
I've been working with Next on AWS Lambda for more than a year, and the lack of official example/support is painful indeed. It's really not easy to properly setup next on AWS, and it's even harder to have a local/dev env that properly simulates AWS Lambda. Also, AWS Lambda is -by far- the most used (compared to GCP, Azure, and others), and it would really make sense for the Next.js community to target this system, as it is one of the cheapest yet most reliable out there. Also, it fits particularly well with the Next 8+ "serverless" approach, but needs guidance to do it right. The most advanced way I've seen so far is https://github.com/danielcondemarin/serverless-nextjs-plugin. I had made my own AWS Lambda + Next 5 + Express back then https://github.com/Vadorequest/serverless-with-next and I'm still running this in production (and looking for an up-to-date replacement, having a hard time to upgrade myself, see #7823) There have been numerous open source attempts to make AWS Lambda work with Next over the past year, I can't count how many work-in-progress repositories I've come across, such as https://github.com/justinwhall/nextjs-serverless-aws The recent Next 9 update brings a lot of much welcomed capabilities/possibilities that are currently in discussion, see serverless-nextjs/serverless-next.js#101 and serverless-nextjs/serverless-next.js#105. So far, I've seen two very different ways to go "serverless" with Next:
Honestly, I don't know what's the best approach here. Both have their pros/cons. Also, I don't know how many existing apps are out there using the "express" way, and it's gonna be hard to migrate apps from "express" to "serverless", as we must find a proper replacement for all middlewares, and other things. So, the point of all this talking is to clarify that there are -at least- 2 ways to use Next.js on AWS, and it hasn't been proved yet that one way is "better" than the other. Also, there is a lot of efforts made by the community to make Next and AWS Lambda play together, but very few successful ones due to the complexity around those. It'd very much be a game changer if the Next.js core team would tackle this issue and provide a reliable way of making Next working on AWS Lambda. |
As far as I know the official way of deploying Next.js is via Now, Zeit's cloud platform. Their platform is serverless as of Now 2.0 and can deploy Next.js and other platforms to both AWS and GCP. The tooling used there is the "next" now-builder (docs) which already generates all the final lambdas and asset artifacts. Presumably there's some production-grade tooling to manage all of that in the respective cloud (AWS/GCP), including setting up S3 buckets and API Gateway for AWS- but that probably belongs to the more proprietary parts of the Now platform (and I don't think that part is open source). With that in mind it seems unlikely that we'll see an official tool to directly push the You can probably take that now-builder above and write a script to orchestrate the final deployment around it. I'm guessing most of the work is getting the full lifecycle sorted out, and based on the experience at my company the API Gateway has always been very painful to work with, even through tooling like serverless as soon as you want to do something like writing a ton of custom routes. |
Updated this reply as it got mis-interpreted. You can read more about deployment here: https://nextjs.org/docs/deployment There's a bunch of community plugins to handle serverless deployments with AWS: The serverless target gives a deployment target independent solution so that it can be used to create solutions for every possible hosting provider. Not just ZEIT, AWS or Google Cloud functions. You can write a solution on top of the serverless target like the community plugins. |
@timneutkens That's a disappointing reply. Totally understand recommending your product for many use cases, but dismissing self-hosting on other serverless platforms because of proprietary optimizations ignores many valid reasons for self-hosting - internal sites on a private network or behind a VPN, sites deployed as part of infra-as-code, etc. I'd love to see Zeit reconsider this position. |
A community plugin exists for hosting using serverless framework: #6173 (comment) The serverless target allows you to host anywhere you want and isn't limited to AWS Lambda as it accepts Node.js However a Next.js app since Next.js 9 is no longer "just a server" as said in my earlier reply. You can't get away with only using AWS Lambda, you also have to serve static pages. When #9524 lands it'll become even more complicated as you'll have to know how to route a page to a static file and lambdas for the same route. Deployment to self-hosted container or server solutions is just |
BTW, I make a small webpack plugin https://github.com/vincent-herlemont/next-aws-lambda-webpack-plugin for get around this issue and allow us to use Next.JS with native AWS solution deployment like SAM or Cloudfomation. |
This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you. |
Hey 👋
Thank you a lot @timneutkens for great #5927 PR, amazing work 🥇
I was going through the code of your PR in order to make it work with AWS Lambda and it was pretty straightforward.
I had to "hack" your
next-serverless-loader.ts
function in order to be able to injectserverless-http
module that way:This is working great, the output can be directly plugged to an handler 🏆
Here are my questions:
serverless-http
module?Cheers ✌️
The text was updated successfully, but these errors were encountered: