Не работает HMR в NodeJS

124
08 декабря 2019, 04:30

Пытаюсь настроить SSR для React приложения, в процессе возникла проблема. Когда я в первый раз запускаю сервер (в development среде), все работает так как и должно (сервер отсылает отрендереный HTML и СSS), после того как я меняю код своего приложения возникает ошибка:

Она возникает потому что код на сервере остался прежний, а на клиенте уже обновился, и react сообщает мне об этой проблеме. Я думаю, что в решении этой проблемы мне поможет технология горячей замены модулей (hot module replacement), но мне не удается ее настроить.

Мой серверный webpack-конфиг выглядит примерно так:

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);
});

Для hot-релоада на сервере использую 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));

Функция renderDocumentToStream занимается тем что преобразует react-компоненты в NodeStram и выглядит примерно так:

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');
  });
}

Когда запускается сервер в консоле можно увидеть что первый console.log выполнился: а второй нет, даже после того как я изменил App.jsx

Что я делают не так?

READ ALSO
не могу переписать код

не могу переписать код

У меня такой код:

127
Запрос на исправление ошибки в тексте

Запрос на исправление ошибки в тексте

Требуется найти готовый сервисРеализация может быть как для Angular (TypeScript), так и обычный JS модуль

134
Как использовать JS библиотеки без NodeJS

Как использовать JS библиотеки без NodeJS

В настоящее время, куда не глянь, любая полезная библиотека подключается к проекту npm install

150