Skip to content
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

Aphrodite / GraphQL / SSR - cannot automatically buffer without a document #326

Open
14850842 opened this issue May 14, 2018 · 5 comments
Open

Comments

@14850842
Copy link

I have implemented a Graphql Server Side Rendered (razzle) react app. We get an intermittent error
cannot automatically buffer without a document when loading the app.
It seems to be an issue when apollow gets the data from the tree and tries to compile the styles at that point.

A suggested method was to call the following:

StyleSheetTestUtils.suppressStyleInjection();
await getDataFromTree(WrappedApp);
StyleSheetTestUtils.clearBufferAndResumeStyleInjection();

But running this gives the intermittent error. Have tried other various technique but have run out of options. Server get request shown below.

server.get("/*", async (req, res, next) => {
  try {
    const client = new ApolloClient({
      ssrMode: true,
      link: createHttpLink({
        uri: process.env.RAZZLE_GQL_HOST,
        fetch: fetch
      }),
      cache: new InMemoryCache()
    });

    const context = {};
    const WrappedApp = (
      <ApolloProvider client={client}>
          <StaticRouter location={req.url} context={context}>
            <App />
          </StaticRouter>
      </ApolloProvider>
    );

    await getDataFromTree(WrappedApp);

    let metaHeader = Helmet.renderStatic();

    const { html, css } = StyleSheetServer.renderStatic(() =>
      renderToStaticMarkup(WrappedApp)
    );

    if (context.url) {
      return res.redirect(context.url);
    } else {
      return res.status(200).send(
        `<!doctype html>
            <html ${metaHeader.htmlAttributes.toString()}>
              <head>
                  <meta httpEquiv="X-UA-Compatible" content="IE=edge" />
                  <meta charset="utf-8">
                  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
                  <style data-aphrodite>${css.content}</style>
                  ${
                    assets.client.css
                      ? `<link rel="stylesheet" href="${assets.client.css}">`
                      : ""
                  }

                  ${
                    process.env.NODE_ENV === "production"
                      ? `<script src="${assets.client.js}" defer></script>`
                      : `<script src="${
                          assets.client.js
                        }" defer crossorigin></script>`
                  }

                  ${metaHeader.title.toString()}
              </head>
              <body>
                  <div id="root">${html}</div>
              </body>
              <script>
                window.__APHRODITE_STATE__=${JSON.stringify(
                  css.renderedClassNames
                )}
                window.__APOLLO_STATE__=${JSON.stringify(
                  client.cache.extract()
                )};
              </script>
          </html>`
      );
    }
  } catch (err) {
    return next(err);
  }
});
@zaklampert
Copy link

Same exact issue here. Any luck?

@DaBs
Copy link

DaBs commented Aug 31, 2018

Same issue here. This essentially makes aphrodite unusable for my current project, which is sad. I'll dig more into some render calls to see what we can do about it.

@adamrneary
Copy link

Same problem at Airbnb. We we're going to implement this at the interface level, swapping out a noop interface for the Aphrodite interface, but if we solve this within aphordite we could use that potentially.

@DaBs
Copy link

DaBs commented Aug 31, 2018

I've got a barebones version working that I will PR soon @adamrneary. I just need to update some documentation for the new methods.

EDIT: I haven't solved the hydration problem in terms of server-side rendering and classes depending upon potential state gained from tree walking with e.g. Apollo, but it does give leeway to using Aphrodite later on in your server-side server logic.

@DaBs
Copy link

DaBs commented Aug 31, 2018

@adamrneary @zaklampert @14850842 This PR aims to solve the basic issue. A better solution would presumably be to extend more of the existing interface to respect server-side rendering, but this is a immediate solution to the problem, assuming you don't need the data from your GraphQL queries to generate classes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants