react hot loader 是什么
React Hot Loader is a plugin for Webpack that allows instantaneous live refresh without losing state while editing React components.
为什么要使用 react hot loader (好处是什么)
- 在我们修改 Component 的时候,只会自动刷新修改的部分,不会刷新整个页面
- 状态不会发生改变
这在我们开发过程中可以极大的提高我们的开发效率,我们不需要在改动一点内容,页面就重新刷新,然后发送一堆请求。
react hot loader 的使用
1. minimal boilerplate
如果只想体验一下 hot loader,或者是只想看看最简单的一个 demo ,那么可以直接参照:
https://github.com/wkwiatek/react-hot-loader-minimal-boilerplate
2. migrating from create-react-app
由于在平时开发中,更多的会使用到 create-react-app 这个脚手架来初始化开发环境,但 create-react-app 中并没有默认配置 hot loader,且把 webpack 的相关配置都给“隐藏”了起来,那么我们需要在 webpack 中去配置 hot loader,我们就需要
- run
npm run eject
//还原配置文件 - Install React Hot Loader (
npm install --save-dev react-hot-loader
) - 在
config/webpack.config.dev.js
中
1 在 entry
中加上 react-hot-loader/patch
entry: [
'react-hot-loader/patch',
require.resolve('react-dev-utils/webpackHotDevClient'),
require.resolve('./polyfills'),
paths.appIndexJs,
]
2 在 babel 配置文件中加入 react-hot-loader/babel
{
test: /\.(js|jsx)$/,
include: paths.appSrc,
loader: require.resolve('babel-loader'),
options: {
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
cacheDirectory: true,
plugins: [
'react-hot-loader/babel'
]
},
},
3 在 src/index.js
使用 AppContainer
wrap App
import React from 'react'
import ReactDOM from 'react-dom'
import { AppContainer } from 'react-hot-loader'
import App from './containers/App'
const render = Component => {
ReactDOM.render(
,
document.getElementById('root'),
)
}
render(App)
// Webpack Hot Module Replacement API
if (module.hot) {
module.hot.accept('./containers/App', () => {
render(App)
})
}
使用
npm run eject
将配置文件还原来实现 hot loader 并不是最佳的方法。
使用 react-app-rewire-hot-loader 来实现 hot loader
使用 react-app-rewire-hot-loader 的好处在于我们不需要执行 npm run eject
来还原配置文件,我们只需要在跟目录下创建一个 config-overriders.js
对 webpack 配置进行拓展。
- package.json
"dependencies": {
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-hot-loader": "^3.1.3",
"react-redux": "^5.0.6",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",
"react-scripts": "1.0.17",
"redux": "^3.7.2",
"redux-devtools": "^3.4.1"
},
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test --env=jsdom",
"eject": "react-app-rewired eject"
},
"devDependencies": {
"react-app-rewire-hot-loader": "^1.0.0",
"react-app-rewired": "^1.3.8",
"standard": "^10.0.3"
}
- 拓展 webpack 配置
//config-overriders.js
const rewireReactHotLoader = require('react-app-rewire-hot-loader');
module.exports = function override(config, env) {
config = rewireReactHotLoader(config, env);
return config;
}
- 监听 reduces
// store.js
import { createStore } from 'redux';
import reducer from './reducer';
let storeInstance
export default function configureStore(initialState) {
storeInstance = storeInstance || createStore(reducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
initialState
);
if (module.hot) {
// Enable Webpack hot module replacement for reducers
module.hot.accept('./reducer', () => {
// const nextRootReducer = require('./reducer');
storeInstance.replaceReducer(reducer);
});
}
return storeInstance;
}
- 使用
AppContainer
wrapApp
import React from 'react';
import { render } from 'react-dom';
import { AppContainer } from 'react-hot-loader'
import { Provider } from 'react-redux'
import configureStore from './store'
import './index.css';
import App from './containers/App';
const store = configureStore()
render(
,
document.getElementById('root')
)
if (module.hot) {
module.hot.accept();
module.hot.dispose((data) => {
data.store = store;
});
}