使用Apollo和React Helmet Async进行服务器端渲染

时间:2018-09-06 22:42:22

标签: reactjs graphql apollo react-helmet

我是Apollo和Graph QL的新手,需要弄清楚如何在此项目中使用react-helmet-async。

这些示例对于现有应用的设置方式并没有多大意义。

我的reactMiddleware.js文件代码如下。有人可以帮我弄清楚如何使用此设置来实现反应头盔异步吗?

// @ts-check

const { ApolloClient } = require('apollo-client');
const { createHttpLink } = require('apollo-link-http');
const { InMemoryCache } = require('apollo-cache-inmemory');
const { getLoadableState } = require('loadable-components/server');
const fetch = require('node-fetch').default;
const React = require('react');
const { renderToStringWithData } = require('react-apollo');
const { renderToString } = require('react-dom/server');
const { StaticRouter } = require('react-router');

function serialize(data) {
  if (!data) {
  return '';
}

const serialized = JSON.stringify(data);
return serialized.replace(/</g, '\\u003c');
}

const isJS = /\.js$/;
const isCSS = /\.css$/;

/**
* @return {import('express').Handler}
*/
module.exports = function reactMiddleware(assets) {
  const createApp = require('../server');

// Grab chunks from the Webpack stats
let runtime = assets['runtime~index'];
if (Array.isArray(runtime)) {
  runtime = runtime.find(file => isJS.test(file));
}

const styles = assets.styles.filter(
  file => isJS.test(file) || isCSS.test(file),
);

const stylesheet = styles.find(file => isCSS.test(file));
const styleScript = styles.find(file => isJS.test(file));

let index = assets.index;
if (Array.isArray(index)) {
  index = index.find(file => isJS.test(file));
}

return function(req, res, next) {
// First, set up the prerequisites. We need:
  // 1. a router to surround the app with, and
// 2. an Apollo GraphQL client.

// Used to capture information from the route rendering (e.g., 404 status codes)
const context = {};

/** @type {React.SFC} */
const Router = ({ children }) =>
React.createElement(
  StaticRouter,
  { context, location: req.path },
  children,
);

const client = new ApolloClient({
    ssrMode: true,
  // @ts-ignore
link: createHttpLink({
  uri: 'http://graphql:8080/graphql',
  fetch,
}),
  cache: new InMemoryCache(),
});

const App = createApp(Router, client);
const root = React.createElement(App);

getLoadableState(root)
  .catch(error => {
  console.error(error);
return {
  getScriptTag() {
    return '';
  },
};
})
.then(async state => {
  let data;
let result;
try {
  result = await renderToStringWithData(root);
data = client.extract();
} catch (error) {
  console.error(error);

result = renderToString(root);
}

// Send down the custom status code if one was used.
res.status(context.statusCode || 200);

const serialized = serialize(data);

const apolloScriptTag =
  serialized &&
          `<script>window.__APOLLO_CLIENT_STATE__ = ${serialized}</script>`;

res.header('Content-Type', 'text/html; charset=utf-8');
res.end(`<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/public/${stylesheet}" />
  <link rel="print" href="/public/print.css" />
  </head>
  <body>
  <div id="root">${result}</div>
${apolloScriptTag}
${state.getScriptTag()}
<script src="/public/${runtime}"></script>
  <script src="/public/${styleScript}"></script>
  <script src="/public/${index}"></script>
  </body>
  </html>`);
})
.catch(error => next(error));
};
};

0 个答案:

没有答案