我正在尝试为React-application设置SSR,当我在开发环境中首次启动服务器时,一切正常(服务器发送浏览器HTML和CSS),更改应用程序的源代码后,我得到了一个错误:
引发此错误是因为服务器上的源代码已过时,但是客户端具有新版本,React会在出现此问题时通知我.我认为解决此问题的方法是称为HMR(热模块替换)的机制,但是对我来说很难设置.
我的服务器Webpack-config看起来像这样:
const serverConfig = merge(commonConfig, {
name: 'server',
target: 'node',
externals: [
nodeExternals({
whitelist: ['webpack/hot/poll?1000'],
}),
],
entry: ['webpack/hot/poll?1000', appServerEntry],
output: {
path: path.resolve(appDist, 'server'),
filename: 'index.js',
},
plugins: [new webpack.HotModuleReplacementPlugin()],
resolve: {
extensions: ['.js', '.jsx', '.json'],
},
});
在每个请求服务器上呈现新版本的UI
app.get('*', (request, response) => {
const staticAssets = getStaticAssets();
const routerContext = {};
const renderStream = renderDocumentToStream({
staticAssets,
request,
routerContext,
});
const cacheStream = createCacheStream(request.path);
response.writeHead(200, { 'Content-Type': 'text/html' });
response.write('<!DOCTYPE html>');
cacheStream.pipe(response);
renderStream.pipe(cacheStream);
});
对于热重装,我使用webpackDevMiddleware和webpackHotMiddleware
const webpackInstance = webpack(webpackConfig);
const clientCompiler = webpackInstance.compilers.find(cmpl => cmpl.name === 'client');
app.use(
webpackDevMiddleware(clientCompiler, {
hot: true,
stats: 'errors-only',
}),
);
app.use(webpackHotMiddleware(clientCompiler));
旨在将App渲染到NodeStream的renderDocumentToStream函数:
import App from './App';
renderDocumentToStream: ({ request, staticAssets, routerContext }) => {
const rootMarkup = renderToString(
<StaticRouter location={request.url} context={routerContext}>
<App />
</StaticRouter>
);
return renderToNodeStream(
<Document
rootMarkup={rootMarkup}
staticAssets={staticAssets}
/>,
);
},
if (module.hot) {
console.log('HERE-0');
module.hot.accept('./App', () => {
console.log('HERE-1');
});
}
服务器在stdout中启动时,记录了console.log的首次调用
即使更改了App.jsx,console.log的第二次调用也未记录
我做错了什么?
解决方法:
该警告明确表明客户端与服务器上的内容不同.这不是一个错误,而是一个警告,这意味着将对性能产生影响,因为React必须在客户端重新渲染,因此实现SSR的整个目的将被挫败.
请检查并确保客户端也获得与服务器相同的水合作用.这应该可以解决问题.