Skip to content

Fix HMR #865

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 8, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion spec/dummy/client/.babelrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{
"presets": ["es2015", "stage-2", "react"]
"presets": [["es2015", {"modules": false}], "stage-2", "react"],
"plugins": [
"react-hot-loader/babel"
]
}
37 changes: 28 additions & 9 deletions spec/dummy/client/app/startup/ClientReduxApp.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import React from 'react';
import { combineReducers, applyMiddleware, createStore } from 'redux';
import { Provider } from 'react-redux';
import middleware from 'redux-thunk';
import thunkMiddleware from 'redux-thunk';
import { AppContainer } from "react-hot-loader";
import { render } from "react-dom";

import reducers from '../reducers/reducersIndex';
import composeInitialState from '../store/composeInitialState';
Expand All @@ -18,19 +20,36 @@ import HelloWorldContainer from '../components/HelloWorldContainer';
* React will see that the state is the same and not do anything.
*
*/
export default (props, railsContext) => {
export default (props, railsContext, domNodeId) => {
const combinedReducer = combineReducers(reducers);
const combinedProps = composeInitialState(props, railsContext);

// This is where we'll put in the middleware for the async function. Placeholder.
// store will have helloWorldData as a top level property
const store = applyMiddleware(middleware)(createStore)(combinedReducer, combinedProps);
const store = createStore(combinedReducer, combinedProps, applyMiddleware(thunkMiddleware));

// Provider uses the this.props.children, so we're not typical React syntax.
// renderApp is a function required for hot reloading. see
// https://github.com/retroalgic/react-on-rails-hot-minimal/blob/master/client/src/entry.js

// Provider uses this.props.children, so we're not typical React syntax.
// This allows redux to add additional props to the HelloWorldContainer.
return (
<Provider store={store}>
<HelloWorldContainer />
</Provider>
);
const renderApp = (Komponent) => {
const element = (
<AppContainer>
<Provider store={store}>
<Komponent />
</Provider>
</AppContainer>
)
render(element, document.getElementById(domNodeId));
}

renderApp(HelloWorldContainer);

if (module.hot) {
module.hot.accept(['../reducers/reducersIndex', '../components/HelloWorldContainer'], () => {
store.replaceReducer(combineReducers(reducers));
renderApp(HelloWorldContainer);
})
}
};
32 changes: 26 additions & 6 deletions spec/dummy/client/app/startup/ClientReduxSharedStoreApp.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import React from 'react';
import { Provider } from 'react-redux';
import ReactOnRails from 'react-on-rails';
import { AppContainer } from "react-hot-loader";
import { render } from "react-dom";

import HelloWorldContainer from '../components/HelloWorldContainer';

Expand All @@ -12,13 +14,31 @@ import HelloWorldContainer from '../components/HelloWorldContainer';
* This is used for the client rendering hook after the page html is rendered.
* React will see that the state is the same and not do anything.
*/
export default () => {
export default (props, railsContext, domNodeId) => {
// This is where we get the existing store.
const store = ReactOnRails.getStore('SharedReduxStore');

return (
<Provider store={store}>
<HelloWorldContainer />
</Provider>
);
// renderApp is a function required for hot reloading. see
// https://github.com/retroalgic/react-on-rails-hot-minimal/blob/master/client/src/entry.js

// Provider uses this.props.children, so we're not typical React syntax.
// This allows redux to add additional props to the HelloWorldContainer.
const renderApp = (Komponent) => {
const element = (
<AppContainer>
<Provider store={store}>
<Komponent />
</Provider>
</AppContainer>
)
render(element, document.getElementById(domNodeId));
}

renderApp(HelloWorldContainer);

if (module.hot) {
module.hot.accept(['../components/HelloWorldContainer'], () => {
renderApp(HelloWorldContainer);
})
}
};
4 changes: 2 additions & 2 deletions spec/dummy/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
"react": "^15.5.4",
"react-dom": "^15.5.4",
"react-helmet": "^5.0.3",
"react-on-rails": "^8.0.1",
"react-hot-loader": "^3.0.0-beta.6",
"react-on-rails": "8.0.2",
"react-proptypes": "^0.0.1",
"react-redux": "^5.0.4",
"react-router": "3.0.5",
Expand All @@ -59,7 +60,6 @@
"eslint-plugin-react": "^6.10.3",
"fbjs": "^0.8.12",
"jsdom": "^9.12.0",
"react-transform-hmr": "^1.0.4",
"tape": "^4.6.3",
"webpack-dev-server": "^2.4.2"
},
Expand Down
11 changes: 8 additions & 3 deletions spec/dummy/client/server-rails-hot.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
// 2. Make sure you have a hot-assets target in your client/package.json
// 3. Start up `foreman start -f Procfile.hot` to start both Rails and the hot reload server.

import webpack from 'webpack';
import WebpackDevServer from 'webpack-dev-server';
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const { resolve } = require('path');
import webpackConfig from './webpack.client.rails.hot.config';
const webpackConfig = require('./webpack.client.rails.hot.config');

const webpackConfigLoader = require('react-on-rails/webpackConfigLoader');
const configPath = resolve('..', 'config');
Expand All @@ -26,6 +26,11 @@ const compiler = webpack(webpackConfig);

const devServer = new WebpackDevServer(compiler, {
contentBase: hotReloadingUrl,
headers: {
'Access-Control-Allow-Origin': '*',
},
disableHostCheck: true,
clientLogLevel: 'info',
hot: true,
inline: true,
historyApiFallback: true,
Expand Down
34 changes: 17 additions & 17 deletions spec/dummy/client/webpack.client.rails.hot.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
// cd client && babel-node server-rails-hot.js
// Note that Foreman (Procfile.dev) has also been configured to take care of this.

// require() is used rather than import because hot reloading with webpack
// requires webpack to transform modules from ES6 to ES5 instead of babel
// and webpack can not transform its own config files.
const { resolve } = require('path');
const webpack = require('webpack');
const merge = require('webpack-merge');
Expand All @@ -11,12 +14,19 @@ const webpackConfigLoader = require('react-on-rails/webpackConfigLoader');
const configPath = resolve('..', 'config');
const { hotReloadingUrl, webpackOutputPath } = webpackConfigLoader(configPath);

module.exports = merge(config, {
// entry is prepended because 'react-hot-loader/patch' must be the very first entry
// for hot reloading to work.
module.exports = merge.strategy(
{
entry: 'prepend'
}
)(config, {

devtool: 'eval-source-map',

entry: {
'app-bundle': [
'react-hot-loader/patch',
`webpack-dev-server/client?${hotReloadingUrl}`,
'webpack/hot/only-dev-server'
],
Expand All @@ -25,6 +35,7 @@ module.exports = merge(config, {
output: {
filename: '[name].js',
path: webpackOutputPath,
publicPath: `${hotReloadingUrl}/`,
},

module: {
Expand All @@ -33,22 +44,6 @@ module.exports = merge(config, {
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
plugins: [
[
'react-transform',
{
transforms: [
{
transform: 'react-transform-hmr',
imports: ['react'],
locals: ['module'],
},
],
},
],
],
},
},
{
test: /\.css$/,
Expand Down Expand Up @@ -111,8 +106,13 @@ module.exports = merge(config, {
],
},

// webpack.NamedModulesPlugin() is an optional module that is great for HMR debugging
// since it transform module IDs (112, 698, etc...) into their respective paths,
// but it can conflict with other libraries that expect global references. When in doubt, throw it out.

plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
],
});
Expand Down
Loading