-
Notifications
You must be signed in to change notification settings - Fork 65
Execute GraphQL queries without http server #936
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
Comments
Thanks @kristoferma How would you handle resolvers that depend on data from the request object? Two options I could see (not saying I like these):
|
Thank you @jasonkuhrt for helping me with this issue. So in the case of Next.js you can access the request object in getServerSideProps and I can imagine it being useful to pass that on to nexus. So my first thought is to have an optional request object parameter with a default value of the equivalent of an empty request object. |
To recap, from graphql-nexus/nexus#782 (comment), the primary motivation for this issue as I understand it is:
One thing I don't fully understand is, what's the fundamental limitation of using |
The limitation that I ran into is that the res object manages the GraphQL response. I want to capture the GraphQL response put it into the Relay Store and pass the Relay Store as props to my Next.js app. Should I make an example of my use case? I feel like we might not be on the same page here. |
This is the most basic example of getServerSideProps. function Page({ data }) {
// Render data...
}
export async function getServerSideProps() {
// Fetch data from external API
const res = await fetch(`https://.../data`)
const data = await res.json()
// Pass data to the page via props
return { props: { data } }
}
export default Page I can do this with nexus function Page({ data }) {
// Render data...
}
export async function getServerSideProps() {
const query = graphql`...`;
const variables = { ... };
// Fetch data from Next.js API Routes
const response = await fetch("https://example.com/api/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
query,
variables,
}),
});
// Get the response as JSON
const json = await response.json();
// Pass data to the page via props
return { props: { data: json } };
}
export default Page But I want to do this function Page({ data }) {
// Render data...
}
export async function getServerSideProps() {
const query = graphql`...`;
const variables = { ... };
// Fetch directly from nexus
const response = await app.schema.exec(query, variables)
// Pass data to the page via props
return { props: { data: JSON.stringify(response) } };
}
export default Page By doing this I get rid of the extra network call from the server side rendering to the graphql endpoint. |
Thanks @kristoferma, we're on the same page about that. What I'm saying is that there is also is third way: export async function getServerSideProps() {
const query = graphql`...`;
const variables = { ... };
// Fetch directly from nexus
const req = ... // get this from nextjs
const res = ... // mock this... /shrug
const response = await app.server.handlers.graphql(req, res)
// Pass data to the page via props
return { props: { data: res.body } };
} I'm not saying that this is good. But it seems to me that it is already possible to avoid the network call. To be clear, I like the idea of direct schema execution access. Between these two directions:
I don't like (2) at all because the abstraction appears odd, its half decoupled from server (no res) but half not (wants req). I like (1) because it feels distinct, clearly an abstraction level lower than the server handlers. I'm thinking right now of an API like But, I could see that being really hard/painful in an app with complex context contributors setup. In such cases, we could help, if the user has access to the req object, which in complex scenarios they ought to, so that we can enable them to build the context themselves like Nexus does internally. const context = await app.schema.makeContext(req) // assumes user has access to req
app.schema.exec(query, vars, context) I think this is reasonable:
Just a sketch of thoughts... still need to think more about it. One thing I'm weary about, generally, is expanding the API surface that 90% of users see with things that only 10% of users use. Not against, just requires extract care to have the correct API nesting, naming, etc. |
Mentioned this before in another thread. This is future-looking, how the API could grow in the future. The key would be some conditional typing that only requires the app.schema.exec('query { foo { bar } }') // OK, foo.bar doesn't use any context
app.schema.exec('query { foo { qux } }') // Error, qux needs some context data
// ~~~
app.schema.exec('query { foo { qux } }', {}, { blah: false }) // fix Getting this information with static analysis would be hard. Getting it dynamically would require running resolvers during reflection which is almost certainly not workable. But would have to think more about either approach more. |
Can this also be applied to using graphQL as a local store, I have been searching for solutions for an offline application that uses a graph on top of local storage to act like an API for the application. I am looking to build an offline-only application that uses graphQL. |
Perceived Problem
Next.js discourages accessing API Routes in server-side code like getStaticProps and getServerSideProps. The encourage users to Write server-side code directly.
Ideas / Proposed Solution(s)
Nexus framework could allow developers to execute graphQL queries directly, without going through the http server.
Some discussion happened here: #782
Working preliminary solution: #921
The text was updated successfully, but these errors were encountered: