Невозможно загрузить исходные скрипты реакции после рендеринга на стороне сервера - PullRequest
0 голосов
/ 12 апреля 2020

Я пытаюсь преобразовать приложение express с отдельным интерфейсом реакции для использования рендеринга на стороне сервера.

У меня есть Apollo и Material-UI.

Сайт загружается правильно со стилями, но я не могу получить доступ ни к одному из сценариев реагирующих компонентов, которые необходимо загрузить после начальной загрузки. Где я ошибаюсь?

Мой express сервер:

const server = express();

const Html = ({
  content,
  state,
  css
}: {
  content: string;
  state: any;
  css: string;
}) => (
  <html>
    <head>
      <style id="jss-server-side" dangerouslySetInnerHTML={{ __html: css }} />
    </head>
    <body>
      <div id="root" dangerouslySetInnerHTML={{ __html: content }} />
      <script
        dangerouslySetInnerHTML={{
          __html: `window.__APOLLO_STATE__=${JSON.stringify(state).replace(
            /</g,
            "\\u003c"
          )};`
        }}
      />
    </body>
  </html>
);

const schema = makeExecutableSchema({ typeDefs, resolvers });
addMockFunctionsToSchema({
  schema,
  preserveResolvers: true
});

server.use((req, res) => {
  const sheets = new ServerStyleSheets();
  const client = new ApolloClient({
    ssrMode: true,
    link: new SchemaLink({ schema }),
    cache: new InMemoryCache()
  });
  const context = {};

  getMarkupFromTree({
    tree: sheets.collect(
      <ApolloProvider client={client}>
        <ThemeProvider theme={theme}>
          <StaticRouter location={req.url} context={context}>
            <Wrapper />
          </StaticRouter>
        </ThemeProvider>
      </ApolloProvider>
    ),
    renderFunction: renderToString
  })
    .then(markup => {
      res.status(200);
      const css = sheets.toString();
      const state = client.extract();
      const html = <Html content={markup} state={state} css={css} />;
      res.send(`<!doctype html>\n${renderToString(html)}`);
      res.end();
    })
    .catch(e => {
      console.error("RENDERING ERROR:", e); // eslint-disable-line no-console
      res.status(500);
      res.end("");
    });
});

server.listen({ port }, () =>
  console.log(`Server ready at http://localhost:${port}`)
);

export default server;

Конфигурация Webpack:

export const clientConfig = {
  entry: {
    main: [
      "webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000",
      "./src/client/index.tsx"
    ]
  },
  output: {
    path: path.join(__dirname, "./src/server/client/build"),
    publicPath: "/",
    filename: "index.js"
  },
  resolve: {
    extensions: [".tsx", ".ts", ".js"]
  },
  mode: "development",
  target: "web",
  devtool: "#source-map",
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-react"],
            plugins: [["@babel/plugin-proposal-decorators", { legacy: true }]]
          }
        }
      },
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"]
      },
      {
        test: /\.ts(x?)$/,
        exclude: /node_modules/,
        use: [
          {
            loader: "ts-loader"
          }
        ]
      }
    ]
  },
  plugins: [new webpack.HotModuleReplacementPlugin()]
};

И я запускаю сервер в режиме разработки через dev-скрипт:

const compiler = webpack(clientConfig);

server.use(
  webpackDevMiddleware(compiler, {
    quiet: true,
    noInfo: true,
    publicPath: clientConfig.output.publicPath
  })
);

server.use(
  webpackHotMiddleware(compiler, {
    log: false
  })
);
...