-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Server-side rendering with graphql endpoint on the same server #962
Comments
@af this is a really interesting issue! One of the ideas we had early on was for the networkInterface to be entirely pluggable. Essentially, as long as it matches the networkInterface API (i.e. query => promise => GraphQLResult), it can be used! So, I think this is totally possible without any core modifications and potentially could be a package you could distribute on npm. // what to match
export interface NetworkInterface {
query(request: Request): Promise<GraphQLResult>;
}
const networkInterface = {
query(request) {
// parse and execute the query here using graphql.js and your own schema
return result : Promise<GraphQLResult>
}
};
const client = new ApolloClient({
ssrMode: true,
networkInterface,
}); I'd be happy to give some advice / guidance if you end up building this route! |
@jbaxleyiii Awesome, so my suggestion 2 was already implemented, I just didn't realize it 😄 I will take a crack at this in the next couple of days and ping you if I need any pointers. Will re-open the issue if I hit anything that looks insurmountable. Thank you for the quick and helpful response! |
@jbaxleyiii So this ended up being much easier than I expected. I haven't fully tested it with all different kinds of queries but this implementation is working great for my app: const createLocalInterface = (graphql, schema, {rootValue = null, context = null} = {}) => {
const {execute} = graphql
return {
query: ({query, variables, operationName, debugName}) => {
return execute(schema, query, rootValue, context, variables, operationName)
}
}
}
module.exports = {createLocalInterface} Since the implementation is so small, I'm wondering if a PR would be considered for adding this to |
Whether or not this gets integrated into apollo-client, here's a really simple npm module that does it: apollo-local-query |
@af The link to your repo might be a good addition to the docs about server-side rendering! |
@helfer suggested adding a section to the docs in [this issue](apollographql/apollo-client#962 (comment))
@af If I spotted this earlier, I don't need to write createApolloClient.server.js |
@helfer suggested adding a section to the docs in [this issue](#962 (comment))
Hi,
I'm using apollo-client to server render a React app. The graphql endpoint is run in the same process as the app that's being rendered, so my
networkInterface
has auri
pointing to localhost.On my local machine everything is working swimmingly. However on other deployment targets where localhost connections are firewalled (eg Heroku), this doesn't work (the server render docs mention that firewalls can be an issue).
Right now my workaround is to point the
uri
to the server's public address, which seems less than ideal from security and performance perspectives. Ideally this app could make server side queries without hitting the network at all, or better yet, by bypassing the http stack entirely.Is this use case one that the apollo-client could provide an "escape hatch" for? It seems like it'd be a fairly common setup for server-rendered apps and the graphql endpoint to be in the same server process. Here are some possible workarounds, please chime in if you have any other ideas:
1) Connect to the graphql endpoint via a Unix domain socket
This should be pretty simple, just have the server also listen on a domain socket, and point the Apollo client's
networkInterface
uri to it. However thewhatwg-fetch
http client used by apollo-client does not support these connections AFAICT. I could monkeypatch the globalfetch
function to support this (yuck), but better yet, maybe the fetch function could be a parameter tonetworkInterface
so the caller could customize it as needed? #645 is somewhat related2) Support server-side queries without using a network interface
This would probably be the most performant and secure solution - instead of using a network interface to make graphql queries, pass in a function that can execute them in-process. Here's a really rough sketch of what that might look like:
Any other suggested approaches for this, or how feasible the two given options are?
The text was updated successfully, but these errors were encountered: