Skip to content

Instantly share code, notes, and snippets.

@jasonnathan
Last active November 18, 2016 02:11
Show Gist options
  • Save jasonnathan/ce319b53db4de0b9f3a0fc90379f95a3 to your computer and use it in GitHub Desktop.
Save jasonnathan/ce319b53db4de0b9f3a0fc90379f95a3 to your computer and use it in GitHub Desktop.
SSR with apollo and meteor-router-ssr
import React from 'react';
import {Meteor} from 'meteor/meteor';
/*
* Had to hack server.jsx in meteor-react-router-ssr to move the `preRender` hook so it runs after
* `wrapperHook` and I had to give it {app} as an extra argument.
*/
import {ReactRouterSSR} from 'meteor/jasonnathan:react-router-ssr';
import ReactHelmet from 'react-helmet';
import AppRoutes from '/imports/routes.jsx';
import ApolloClient, {createNetworkInterface} from 'apollo-client';
import {ApolloProvider} from 'react-apollo';
import {getDataFromTree} from "react-apollo/server";
let client, initialState,
url = "localhost",
opts = {
ssrMode: Meteor.isServer
};
// relevant for apollo when a client-side query is made
if(Meteor.isClient && process.env.NODE_ENV === 'production'){
url = "public-url.com";
}
// setup apollo's networkInterface
opts.networkInterface = createNetworkInterface({
credentials: 'same-origin', uri: `http://${url}:3000/graphql`
});
const rehydrateHook = state => initialState = state;
const wrapperHook = app => {
opts.initialState = initialState;
client = new ApolloClient(opts);
return <ApolloProvider client={client}>{app}</ApolloProvider>
};
// the preRender is simpler. All it needed was the `app` argument
const preRender = (req, res, app) => Promise.await(getDataFromTree(app));
// dehydrating in a way that is apollo friendly. Queries & mutations need to be removed
const dehydrateHook = () => ({apollo:{data:client.store.getState().apollo.data}})
const htmlHook = html => {
const h = ReactHelmet.rewind();
return html.replace('<head>', '<head>' + h.title + h.base + h.meta + h.link + h.script);
}
// the weirdest thing - wrapperHook in clientOptions - inferring it only runs on the client
const clientOptions = {wrapperHook, rehydrateHook};
const serverOptions = {htmlHook, preRender, dehydrateHook};
ReactRouterSSR.Run(AppRoutes(), clientOptions, serverOptions);
// from line 190
// if (serverOptions.preRender) {
// serverOptions.preRender(req, res);
// }
//...
global.__STYLE_COLLECTOR_MODULES__ = [];
global.__STYLE_COLLECTOR__ = '';
renderProps = {
...renderProps,
...serverOptions.props
};
fetchComponentData(serverOptions, renderProps);
let app = <RouterContext {...renderProps} />;
if (typeof clientOptions.wrapperHook === 'function') {
app = clientOptions.wrapperHook(app);
}
// preRender moved after wrapperHook
if (serverOptions.preRender) {
serverOptions.preRender(req, res, app);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment