Meteor 1.8.1 SSR + Apollo + React Router 5 + Dynamic Import / Code Splitting / React Loadable Voodoo

Hi,

I’m trying to make all these packages work together and am running into some trouble. Unfortunately many of the guides and tutorials on official sites are outdated :frowning:

Issues:

  1. server-render server side version isn’t rendering apollo content
  2. Having a screen flash with React Loadable

Here’s my mish-mash of code from various (possibly outdated) sources. Looking for latest-and-greatest guidance.

server:

import { Meteor } from "meteor/meteor";
import React from "react";
import Loadable from "react-loadable";
import { renderToString } from "react-dom/server";
import { onPageLoad } from "meteor/server-render";
import { getUser } from "meteor/apollo";
import ApolloClient from "apollo-client";
import { ApolloProvider } from "react-apollo";
import { InMemoryCache } from "apollo-cache-inmemory";
import { SchemaLink } from "apollo-link-schema";

import "isomorphic-fetch";
import { Helmet } from "react-helmet";
import { StaticRouter } from "react-router-dom";
import App from "./App.js";
import schema from "/imports/startup/server/schema.js";

Loadable.preloadAll();

onPageLoad(async sink => {
  // const { loginToken } = sink.getCookies();
  const user = await getUser(sink.request.headers.authorization);

  const client = new ApolloClient({
    ssrMode: true,
    link: new SchemaLink({
      schema,
      context: { user, userId: user ? user._id : undefined }
    }),
    cache: new InMemoryCache()
  });

  const context = {};
  const modules = [];

  sink.renderIntoElementById(
    "app",
    renderToString(
      <Loadable.Capture report={moduleName => modules.push(moduleName)}>
        <ApolloProvider client={client}>
          <StaticRouter location={sink.request.url} context={context}>
            <App />
          </StaticRouter>
        </ApolloProvider>
      </Loadable.Capture>
    )
  );

  const helmet = Helmet.renderStatic();
  sink.appendToHead(helmet.meta.toString());
  sink.appendToHead(helmet.title.toString());
  sink.appendToHead(helmet.link.toString());
});