React-Hot-Loader v3
安装
npm install --save react-hot-loader
注意: 你可以 install react-hot-loader 作为一个常规的 dependency,而不是 dev dependency,因为它会自动的确保不会在生产环境执行,并且它留下的痕迹是非常小的。
开始使用
- 在
.babelrc
里面增加react-hot-loader/babel
:
// .babelrc
{
"plugins": ["react-hot-loader/babel"]
}
-
在Webpack config 的 entry 最顶部(除开polyfills)添加
react-hot-loader/patch
:
// webpack.config.js
module.exports = {
entry: [
'babel-polyfill',
'react-hot-loader/patch',
'./main.js'
]
}
注意:保证把
output.publicPath
属性设置成"/"
。以保证 hot reloading 会在嵌套的路由有效。
- 把你的应用包裹在
<AppContainer>
,当发生更新所有<AppContainer>
的 children 会 reloaded。
// main.js
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(
<AppContainer>
<Component />
</AppContainer>,
document.getElementById('root'),
)
}
render(App)
// Webpack Hot Module Replacement API
if (module.hot) {
module.hot.accept('./containers/App', () => { render(App) })
}
为了使上面有效,你需要不使用 Babel 编译 ES2015 的模块,通过把 Babel ES2015 的 preset 改为
["es2015", { "modules": false }]
使用 Webpack loader 取代 Babel plugin
也许你没有在你的工程里面使用 Babel, React Hot Loader 提供了一个 Webpack loader 可以提供一些限制性的功能,如果你想用它,你可以添加到你 Webpack config里面。如果你不使用babel,你不需要增加这个loader
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.jsx?$/,
use: ['react-hot-loader/webpack']
}
]
}
}
已知的局限性
组件不会被替换
- React Hot Loader 不会替换任何的组件, 只是 register 了它。
- 当使用 webpack loader - 仅仅只有export 的模块会被 register
- 当使用 babel plugin - 仅仅顶层的变量才会被 register
- 当 React Hot Loader 不能替换 Component, 将会显示错误信息
Code Splitting
如果你想使用 Webpack 通过 require.ensure
切割代码,你必须在 require.ensure
代码块增加额外的 module.hot.accept
回调, 就像这样:
require.ensure([], (require) => {
if (module.hot) {
module.hot.accept('../components/App', () => {
loadComponent(require('../components/App').default);
})
}
loadComponent(require('../components/App').default);
});
注意如果你使用 React Router (4.0版本之前), 这个只会对 getChildRoutes
有效, 但对 getComponent
无效, 因为 getComponent
's 的回调只会加载 component 一次。
同样, 如果你使用 Webpack 2 beta, 你可以使用 System.import
而不需要额外的 module.hot.accept
调用, 当然这里现在有一些 issues .
检查 Element 的 type
因为 React Hot Loader 为你的组件创建了一个 proxy 的版本,比较 element 的type引用是没有用的:
const element = <Component />;
console.log(element.type === Component); // false
有一种变通的方法,创建一个 element (它会有被 proxy 组件的 type
属性 ):
const ComponentType = (<Component />).type;
const element = <Component />;
console.log(element.type === ComponentType); // true
你同样可以在 component 的 class 上设置一个属性:
const Widget = () => <div>hi</div>;
Widget.isWidgetType = true;
console.log(<Widget />.type.isWidgetType); // true
重新对 Component 赋值
React Hot Loader 将会 reload 原来组件引用,所以当你把另外一个变量重新赋值给该组件时,就像下面一样:
let App = () => (<div>hello</div>);
App = connect()(App);
export default App;
React Hot Loader 将不会重新 reload, 你必须重新定义一次:
const App = () => (<div>hello</div>);
export default connect()(App);
Decorators
Components 如果被 decorated 过(比如用 @autobind
),现在这种情况当 hot-reloaded 不会保留 state。(参看#279)