客户端路由更改后,React 服务器端渲染未更新

时间:2021-05-09 10:37:06

标签: javascript node.js reactjs express server-side-rendering

第一次刷新了服务端,但是下一次,照常只改变了客户端,服务端没有改变。

例如,每次刷新或在浏览器中输入地址时,服务器也会更改并正常工作,但是如果我使用 react router 在客户端的页面之间切换,服务器不会更改。

有什么问题?

#server/server.js

import path from 'path';
import fs from 'fs';

import express from 'express';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import { StaticRouter } from 'react-router-dom';

import App from '../src/App';

const PORT = 5000;
const app = express();

const router = express.Router();
app.use('/build', express.static('build'));

app.use((req, res, next) => {
  if (/\.js|\.css|\.png|\.jpg|\.jpeg/.test(req.path)) {
    res.redirect('/build' + req.path);
  } else {
    next();
  }
})
app.get('*', (req, res) => {
  const context = {};
  const app = ReactDOMServer.renderToString(
    <StaticRouter location={req.path} context={context}>
      <App />
    </StaticRouter>
  );

  const indexFile = path.resolve('./build/index.html');
  fs.readFile(indexFile, 'utf-8', (err, data) => {
    if (err) {
      console.log("Something went wrong:", err);
      return res.status(500).send("Oops, better luck next time!");
    }

    return res.send(data.replace('<div id="root"></div>', `<div id="root">${app}</div>`));
  });
});

router.use(express.static(path.resolve(__dirname, '..', 'build'), { maxAge: '10d' }));

app.use(router);

app.listen(PORT, () => {
  console.log(`SSR running on ${PORT}`);
});

#server/index.js

require('ignore-styles');

require('@babel/register')({
    ignore: [/(node_module)/],
    presets: ['@babel/preset-env', '@babel/preset-react'],
    plugins: ['@babel/transform-runtime'],
});

require('./server');

#index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import * as serviceWorker from './serviceWorker';
import App from './App';

ReactDOM.hydrate(
  <BrowserRouter>
      <App />
  </BrowserRouter>,
  document.getElementById('root')
);

1 个答案:

答案 0 :(得分:1)

您的服务器端渲染设置没有任何问题。这就是幕后发生的事情。

当您第一次键入并输入应用程序路由的 URL 或刷新浏览器选项卡时,它会访问服务器并在 {{1} 的帮助下加载在服务器端呈现的 index.html 文件}.

renderToString

然后查看 ReactDOMServer.renderToString(...)` 并将其添加到此框架 HTML 文件中(附加事件处理程序...等)。

请注意,您从 build 文件夹加载 index.html 并仅将 div 替换为 root 作为 ID。构建应用程序后,它添加 js 资源需要更改 index.html(这些资源实际上是您为应用程序编写的前端逻辑),这是 DOM 呈现所必需的。如果您选中 client-side,则它具有以下脚本标记来加载它们。

index.html

当您点击应用内的链接前往另一条路线时。它不会再次访问服务器,并开始执行从客户端包中附加的 js,正如我上面所说的。客户端 js 正确执行应用程序的路由。这就是它没有访问您的服务器的原因。这是 ... <script src="/static/js/xxxxxxxxxxxxxxx.chunk.js"> ... 的预期性质(在服务器端或客户端的行为相同)。之后,如果您刷新浏览器,它会再次从服务器加载 isomorphic web application