Closed naranoeur closed 3 years ago
Same here, I tried with this code, and get another error stack trace:
// file: pages/api/graphql.js
const typeDefs = {...};
const resolvers = {...};
export default (async () => {
const server = new ApolloServer({ typeDefs, resolvers, playground: true });
await server.start();
const handler = server.createHandler();
return handler;
})();
TypeError: resolver is not a function
at apiResolver (/Users/carlosazaustre/dev/recipe-web-app/node_modules/next/dist/next-server/server/api-utils.js:8:7)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async DevServer.handleApiRequest (/Users/carlosazaustre/dev/recipe-web-app/node_modules/next/dist/next-server/server/next-server.js:66:462)
at async Object.fn (/Users/carlosazaustre/dev/recipe-web-app/node_modules/next/dist/next-server/server/next-server.js:58:580)
at async Router.execute (/Users/carlosazaustre/dev/recipe-web-app/node_modules/next/dist/next-server/server/router.js:25:67)
at async DevServer.run (/Users/carlosazaustre/dev/recipe-web-app/node_modules/next/dist/next-server/server/next-server.js:68:1042)
at async DevServer.handleRequest (/Users/carlosazaustre/dev/recipe-web-app/node_modules/next/dist/next-server/server/next-server.js:32:504)
🎉 Solved!
You need to install micro
along as apollo-server-micro
,
And this is the code that works, kudos to William Lyon (@lyonwj)
import { ApolloServer, gql } from "apollo-server-micro";
const typeDefs = {...};
const resolvers = {...};
const apolloServer = new ApolloServer({
typeDefs,
resolvers,
});
const startServer = apolloServer.start();
export default async function handler(req, res) {
await startServer;
await apolloServer.createHandler({
path: "/api/graphql",
})(req, res);
}
export const config = {
api: {
bodyParser: false,
},
};
@carlosazaustre While that does work, it does not address the original issue.
Apollo's documentation state Call start only if you are using a middleware integration for a non-"serverless" environment .
Most Next.JS projects are "serverless" and will have a negative performance impact by calling .start()
Apollo do not count apollo-server-micro
as a serverless package, but most users are probably using it in a serverless environment. There should be a mode to allow apollo-server-micro
to operate in a serverless mode similar to apollo-server-lambda
.
When selecting Apollo server package, I could not find documentation for which package was best suited for next.js. Most tutorials use apollo-server-micro, and it did work until now.
It states that apollo-server-lambda is for the AWS Lambda, and then there are specific packages for Azure, Google, Cloudfare. So apollo-server-lamda, along with the other platform specific packages did not seem to be the right package to use for Next.js app.
I'm really confused. It's not only apollo that does not count micro as a serverless package, but also vercel. In the micro readme it says this:
Disclaimer: Micro was created for use within containers and is not intended for use in serverless environments. For those using Vercel, this means that there is no requirement to use Micro in your projects as the benefits it provides are not applicable to the platform. Utility features provided by Micro, such as json, are readily available in the form of Serverless Function helpers.
So why is next.js using micro
in its examples? Is it the same as any other HTTP microservice package? If so it wouldn't make sense for only apollo-server-micro
to have a "serverless mode". If someone could help clear this up for me, that would be great.
I came up with a solution like @carlosazaustre, it works fine. However, I'm facing an issue of integrating the Apollo Subscription into next.js. The issue located here https://github.com/apollographql/apollo-server/issues/2639 still cannot resolve the issue. I really want to make the server located in same origin with Next.js, but I'm not sure whether it affects the performance. If anyone has a solution for this, please post it here, many thanks!
ntegrating the Apollo Subscription into next.js. The issue located here #2639 still cannot resolve the issue. I really want to make the server located
But your solution isn't really addressing the original issue, is it? Are you calling .start()?
I don't think we make any claim that Apollo Server works out of the box with Next.js. I honestly am having trouble understanding what the difference between Next.js and micro is exactly — is there a concise explanation in their docs that I'm not finding? I get that they are somehow related and both come from Vercel, but a Google search for site:nextjs.org "micro"
turns up nothing, and Next is not mentioned in the minimal micro docs.
It sounds like Next.js is popular and it would be cool if there was an easy way to use Apollo Server with it (though perhaps this could be a community package, as we are still hoping to move in the direction of fewer framework integrations maintained directly by a core team who doesn't actually use most of them), but I don't think we make any claims that it does today so I don't think this is a bug?
I did a bit more research and I found this thread which suggests that by enabling the webpack experiment named topLevelAwait
you can just do await server.start()
at the top level in your Next.js API route. Does that solve this issue?
@glasser I don't think that was the main issue, though many people were definitely struggling with that. The main issue is #5547 (comment):
Most Next.JS projects are "serverless" and will have a negative performance impact by calling .start()
I'm assuming this can only be solved with an apollo-server-nextjs
though.
I mean, startup has to happen for Apollo Server to work, one way or the other. The lambda and cloud functions ones put that into the first request handler, which isn't particularly great.
Hey @glasser I noticed you've been reaching out to developers for clarification on this issue and I really appreciate that. But I feel issues like this popup due to a surprising lack of information on how to integrate Apollo and Next.JS
@stemmlerjs @kkemple have written blog posts about Apollo Client, but nothing about Apollo Server, and nothing past a getting started.
For example, those posts also don't explain to enable Apollo Client's SSR using getDataFromTree with Next.JS. There is a discussion with 100+ comments but there's no consensus on a solution. The recommended solutions are manually build your own cache by importing every query that will be run. Which doesn't scale past a getting started example.
Maybe this needs a community solution, but I'm hoping someone from Apollo's Developer Advocate team could write blog post could clarify exactly how to use Apollo Server with Next.JS which also show cases how to incorporate advanced Apollo features like getDataFromTree
.
Thanks for this @marklawlor - I'll pass this to our devrel team. Getting more concrete examples put together that show how to use Next.js with Apollo Client and Apollo Server is definitely something we want to do, and enhancing our SSR approach in Apollo Client to make sure it works more seamlessly with Next specifically, is something we're planning.
I'm just finally upgrading my project to the latest NextJS 11 and the latest apollo-server-micro. Is there a best practice for this yet? I see references to topLevelAwait
or wrapping the handler. Or maybe some other solution?
@tettoffensive The Apollo Server team continues to not understand what the relationship between NextJS and Micro is and why you would want to use them together, other than the existence of an example that combines them.
@glasser I see. I'm guessing most are using it precisely because of this example. When I learned how to use graphql with NextJS 9 this is what I've found. Now I'm taking this old project which previously just needed the lines:
const handler = apolloServer.createHandler({ path: '/api/graphql' });
export default withSession<NextIronHandler>(handler);
But something changed in the upgrade and now it wants apolloServer.start()
to run first
Yes, I asked the author of the example why they chose Micro a couple of months ago and haven't heard back.
I'm not sure why its the communities responsibility to explain why the Apollo/NextJS user base is using micro
. In lieu of an official example, the community is going to use the best (only?) documented solution.
Continuing this discussion a little bit, if people are interested in using Apollo Server with NextJS, codepen.io recently blogged on how they are using NextJS and Apollo. However the NextJS devs responded that this may have performance impacts, (direct link to comment) make sure you understand those gotchas.
The apollo-server-vercel also exists, but recently updated their README to explain that the project is still under development and has no guarantee of maintenance.
Thanks @marklawlor. I'll just stick with 2.0 for now. Not worth messing with for me.
I filed https://github.com/vercel/next.js/pull/30082 to fix Next.js's examples.
Stumbled upon this thread while updating some of my code. As much as I like apollo-server-micro
I've ended up switching to the new release of graphql-yoga
for my serverless API deployed on Vercel.
I was pretty wary of using micro from the beginning as there seems to be a lot of unknowns on the fate of the project, and even then using it for my serverless API didn't seem like it was what the package was made for.
Either way:
// from
const api = new ApolloServer({
schema,
context: createContext,
playground: true,
introspection: true,
}).createHandler({
path: "/api",
});
// to
const server = createServer<{
req: NextApiRequest;
res: NextApiResponse;
}>({
endpoint: "/api",
schema,
context: createContext,
maskedErrors: false,
});
The above was all I needed to have the same implementation. Hope this helps someone.
@creativiii Thanks for this. I've been using: https://github.com/apuyou/apollo-server-nextjs, but it does seem like graphql-yoga
might be a good solution since they actually mention Next.js integration in their docs: https://www.graphql-yoga.com/docs/integrations/integration-with-nextjs
@tettoffensive Have you been able to successfully get subscriptions working with graphql-yoga
in your Next project?
@tettoffensive Have you been able to successfully get subscriptions working with
graphql-yoga
in your Next project?
Haven't tried subscriptions. I'm using graphql-yoga and it's been great. Pulled in a different direction for now. If you get it working I'd love to hear about it!
this is updated and appears to work https://github.com/vercel/next.js/blob/canary/examples/api-routes-apollo-server-and-client
this is updated and appears to work https://github.com/vercel/next.js/blob/canary/examples/api-routes-apollo-server-and-client
That's running version 2.x.
The code was working fine with apollo-server-micro@2.25.1, but now with apollo-server-micro@^3.0.2, it breaks.
It should be able to createHandler for Next.js without starting the server, since Next.js api routes run in server less environment. I tried starting the server first, but then the handler it produces, Next.js cannot use and throws errors.
Error with stack trace:
Error: You must
await server.start()before calling
server.createHandler()at ApolloServer.assertStarted (/Users/naranoeur/Desktop/projects/graphql-blog/node_modules/apollo-server-core/dist/ApolloServer.js:242:19) at ApolloServer.createHandler (/Users/naranoeur/Desktop/projects/graphql-blog/node_modules/apollo-server-micro/dist/ApolloServer.js:13:14) at eval (webpack-internal:///./pages/api/graphql.js:72:30) at Object../pages/api/graphql.js (/Users/naranoeur/Desktop/projects/graphql-blog/.next/server/pages/api/graphql.js:22:1) at __webpack_require__ (/Users/naranoeur/Desktop/projects/graphql-blog/.next/server/webpack-runtime.js:33:42) at __webpack_exec__ (/Users/naranoeur/Desktop/projects/graphql-blog/.next/server/pages/api/graphql.js:54:52) at /Users/naranoeur/Desktop/projects/graphql-blog/.next/server/pages/api/graphql.js:55:28 at Object.<anonymous> (/Users/naranoeur/Desktop/projects/graphql-blog/.next/server/pages/api/graphql.js:58:3) at Module._compile (node:internal/modules/cjs/loader:1095:14) at Object.Module._extensions..js (node:internal/modules/cjs/loader:1124:10)