web-dev-qa-db-fra.com

Le contenu du texte ne correspond pas. Avertissement dans React 16

J'essaie de créer une application ReactJs avec un rendu côté serveur Mes points d'entrée pour le client et le serveur:

client.jsx

const store = createStore(window.__INITIAL_STATE__);

hydrate(
  <Provider store={store}>
    <BrowserRouter>{renderRoutes(routes)}</BrowserRouter>
  </Provider>,
  document.querySelector('#root')
);

server.jsx

const app = express();

if (isDev) {
  const webpack = require('webpack');
  const webpackDevMiddleware = require('webpack-dev-middleware');
  const config = require('../../webpack.config.js');
  const compiler = webpack(config);

  app.use(express.static('/public'));
  app.use(
    webpackDevMiddleware(compiler, {
      publicPath: config.output.publicPath,
      stats: 'errors-only',
    })
  );
}

app.get('*', (req, res) => {
  const helmet = Helmet.renderStatic();
  const htmlAttrs = helmet.htmlAttributes.toComponent();
  const bodyAttrs = helmet.bodyAttributes.toComponent();

  const context = {};
  const data = {};

  res.set('content-type', 'text/html');

  res.send(
    '<!DOCTYPE html>' +
      renderToString(
        <html {...htmlAttrs}>
          <head>
            {helmet.title.toComponent()}
            {helmet.meta.toComponent()}
            {helmet.link.toComponent()}
          </head>
          <body {...bodyAttrs}>
            <div id="root">
              <StaticRouter location={req.url} context={context}>
                {renderRoutes(routes)}
              </StaticRouter>
            </div>
            <script
              dangerouslySetInnerHTML={{
                __html: `window.__INITIAL_STATE__ = ${JSON.stringify(data)}`,
              }}
            />
            <script src="/public/vendor.js" />
            <script src="/public/app.js" />
          </body>
        </html>
      )
  );
});

Et composant:

home.jsx

import React, { Component } from 'react';

class Home extends Component {
  render() {
    return <div>home</div>;
  }
}

export default Home;

Lorsque je modifie mon composant Home et actualise la page du navigateur, j'obtiens cette erreur:

Avertissement: le contenu du texte ne correspond pas. Serveur: "home" Client: "home1"

C'est ok parce que le serveur rend l'ancienne version de mon code. Comment recharger le code sur le serveur pour que les versions client et serveur soient égales?

13
Pavel

Le problème ici est que votre application côté serveur ne reflète pas les modifications de code. Pour ce faire, vous devez configurer votre application express en tant qu'entrée de webpack.

En bref, vous avez besoin de 2 configurations de webpack, une pour le serveur et une autre pour le code client. Le serveur ressemblera à ceci

module.exports = {
  entry: {
    server: './server.js',
  },
  output: {
    path: path.join(__dirname, 'dist'),
    publicPath: '/',
    filename: '[name].js'
  },
  target: 'node',
  node: {
    // Need this when working with express, otherwise the build fails
    __dirname: false,   // if you don't put this is, __dirname
    __filename: false,  // and __filename return blank or /
  },
  externals: [nodeExternals()], // Need this to avoid error when working with Express
  module: {
    rules: [
      {
        // Transpiles ES6-8 into ES5
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      },
      {
        // Loads the javacript into html template provided.
        // Entry point is set below in HtmlWebPackPlugin in Plugins 
        test: /\.html$/,
        use: [{loader: "html-loader"}]
      }
    ]
  },
  plugins: [
    new HtmlWebPackPlugin({
      template: "./index.html",
      filename: "./index.html",
      excludeChunks: [ 'server' ]
    })
  ]
}

Voici un Nice article expliquant comment le faire en détail

2
mpospelov