-
-
Save Chun-Lin/ca10837bc650da1765bca352f2f83686 to your computer and use it in GitHub Desktop.
Webpack React/Redux Hot Module Reloading (HMR) example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
import ReactDOM from "react-dom"; | |
import configureStore from "./store/configureStore"; | |
const store = configureStore(); | |
const rootEl = document.getElementById("root"); | |
let render = () => { | |
const RootAppComponent = require("containers/RootAppComponent").default; | |
ReactDOM.render( | |
<RootAppComponent store={store} />, | |
rootEl | |
); | |
}; | |
if(module.hot) { | |
// Support hot reloading of components | |
// and display an overlay for runtime errors | |
const renderApp = render; | |
const renderError = (error) => { | |
const RedBox = require("redbox-react"); | |
ReactDOM.render( | |
<RedBox error={error} />, | |
rootEl, | |
); | |
}; | |
render = () => { | |
try { | |
renderApp(); | |
} | |
catch(error) { | |
renderError(error); | |
} | |
}; | |
module.hot.accept("./containers/Root", () => { | |
setTimeout(render); | |
}); | |
} | |
render(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {createStore, applyMiddleware, compose} from "redux"; | |
import rootReducer from "../reducers/rootReducer"; | |
import thunk from "redux-thunk"; | |
import createSagaMiddleware from 'redux-saga'; | |
import SagaManager from "sagas/SagaManager"; | |
/** | |
* Based on the current environment variable, we need to make sure | |
* to exclude any DevTools-related code from the production builds. | |
* The code is envify'd - using 'DefinePlugin' in Webpack. | |
*/ | |
const sagaMiddleware = createSagaMiddleware(); | |
const middlewares = [thunk, sagaMiddleware]; | |
const storeEnhancers = []; | |
if(__DEV__) { | |
const DevTools = require("../containers/DevTools").default; | |
// If the user has the "Redux DevTools" browser extension installed, use that. | |
// Otherwise, hook up the in-page DevTools UI component. | |
const debugEnhancer = window.devToolsExtension ? window.devToolsExtension() : DevTools.instrument(); | |
storeEnhancers.push(debugEnhancer); | |
} | |
const middlewareEnhancer = applyMiddleware(...middlewares); | |
storeEnhancers.unshift(middlewareEnhancer); | |
export default function configureStore(initialState) { | |
const store = createStore( | |
rootReducer, | |
initialState, | |
compose(...storeEnhancers) | |
); | |
// run sagas | |
SagaManager.startSagas(sagaMiddleware); | |
if(__DEV__) { | |
// Hot reload reducers (requires Webpack or Browserify HMR to be enabled) | |
if(module.hot) { | |
module.hot.accept("../reducers/rootReducer", () => | |
store.replaceReducer(require("../reducers/rootReducer").default) | |
); | |
module.hot.accept('../sagas/SagaManager', () => { | |
SagaManager.cancelSagas(store); | |
require('../sagas/SagaManager').default.startSagas(sagaMiddleware); | |
}); | |
} | |
} | |
return store; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Borrowed from https://gist.github.com/hoschi/6538249ad079116840825e20c48f1690 | |
// Note that reloading sagas has several issues/caveats to be aware of. | |
// See https://github.com/yelouafi/redux-saga/issues/22#issuecomment-218737951 for discussion. | |
import { take, fork, cancel } from 'redux-saga/effects'; | |
import rootSaga from "./rootSaga"; | |
const sagas = [rootSaga]; | |
export const CANCEL_SAGAS_HMR = 'CANCEL_SAGAS_HMR'; | |
function createAbortableSaga (saga) { | |
if (process.env.NODE_ENV === 'development') { | |
return function* main () { | |
const sagaTask = yield fork(saga); | |
yield take(CANCEL_SAGAS_HMR); | |
yield cancel(sagaTask); | |
}; | |
} else { | |
return saga; | |
} | |
} | |
const SagaManager = { | |
startSagas(sagaMiddleware) { | |
sagas.map(createAbortableSaga).forEach((saga) => sagaMiddleware.run(saga)); | |
}, | |
cancelSagas(store) { | |
store.dispatch({ | |
type: CANCEL_SAGAS_HMR | |
}); | |
} | |
}; | |
export default SagaManager; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment