Замена горячего модуля 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, потому что состояние вашего приложения не изменится, когда вы перерисовываете свое приложение.