Замена горячего модуля Webpack + React

Возможно, это один из тысяч подобных вопросов, но я до сих пор не нашел ответа о том, как заставить HMR действительно работать.

Я сделал все эти манипуляции, описанные в документации, и в каждом ответе вы можете найти по всему интернету:

  • включить "горячую" опцию webpack-dev-server
  • добавлять webpack-dev-server/client?{host:port} а также webpack/hot/only-dev-server точки входа
  • добавлять new webpack.HotModuleReplacementPlugin() к плагинам (и NamedModulesPlugin тоже)
  • каждый шаг из документации по реагированию на горячую загрузку

А теперь то, что у меня есть.

Допустим, мое приложение выглядит так:

<ReactRouter>
  <App>
    <AppRouter />
  </App>
</ReactRouter>

где AppRouter как

<Switch>
  <Route path="..." component={Page} />
  ...
</Switch>

а также Page просто <div>some text<div>,

В соответствии с документами, в модуле приложения я делаю:

import { hot } from "react-hot-loader"
export default hot(module)(App)

а затем пытается изменить текст в Page компонент для "нового текста".

В консоли я вижу, что HMR действительно включен:

[WDS] App hot update...
[HMR] Checking for updates on the server...
[HMR] Updated modules:
[HMR]  - ./Page.js
[HMR]  - ./AppRouter.js
[HMR]  - ./App.js
[HMR] App is up to date.

и текст на экране действительно обновляется до "нового текста". Все идет нормально.

Затем я обновляю текст еще раз, чтобы "новый текст 2", и вижу это:

Ignored an update to unaccepted module ./Page.js -> ./AppRouter.js -> ./App.js
[HMR] The following modules couldn't be hot updated: (They would need a full reload!)
[HMR]  - ./Page.js

В этом нет ничего react-hot-loader Docs.

Но хорошо, возможно, этот документ немного неверен. В конце концов, собственные документы webpack явно показывают, что мы должны делать module.hot.accept(...) в нашем коде.

Так в App.js Я делаю:

if (module.hot) {
  module.hot.accept("./AppRouter", () => {
    console.log("It works!")
  })
}

затем обновить страницу и попытаться изменить Page Компонент снова.

Теперь консоль говорит следующее:

[WDS] App hot update...
[HMR] Checking for updates on the server...
App.js:20 It works!
[HMR] Updated modules:
[HMR]  - ./Page.js
[HMR]  - ./AppRouter.js
[HMR]  - ./App.js
[HMR] App is up to date.

Но текст в браузере не обновляется. Т.е. HMR включен, но ничего не делает.

Последующие обновления говорят:

[WDS] App hot update...
[HMR] Checking for updates on the server...
[HMR] Updated modules:
[HMR]  - ./Page.js
[HMR] App is up to date.

так по крайней мере мы исправили предыдущую ошибку с unaccepted changes - но все равно ничего не меняется в браузере.

Я пытался сделать module.hot.accept(...) оба, когда приложение украшено hot(module) а когда нет - результат тот же.

И... что дальше? Я сделал все, что я могу найти в официальных документах, и ничего из этого не работает. Что я делаю неправильно?

(и, пожалуйста, не просите "предоставить полную конфигурацию веб-пакета, прежде чем мы поговорим". Это все по умолчанию, в соответствии с примером из документации веб-пакета. Не тратьте на это наше время)

1 ответ

Когда вы принимаете файл, вы должны все делать самостоятельно (например, обмен компонента). Так и дела. как это:

if (module.hot) {
  module.hot.accept("./AppRouter", () => {
    const NewAppRouter = require('./AppRouter').default;
    const newApp = (
       <ReactRouter>
          <App>
             <NewAppRouter />
          </App>
       </ReactRouter>
    );
    ReactDom.render(newApp, container);
  });
}

Здесь я получаю уведомление, когда файл изменился. Затем я требую измененный файл и заново создаю приложение с новым файлом. Это работает лучше всего, когда вы используете библиотеку управления состояниями, такую ​​как redux или mobx, потому что состояние вашего приложения не изменится, когда вы перерисовываете свое приложение.

Другие вопросы по тегам