-
Notifications
You must be signed in to change notification settings - Fork 879
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
React Hot Loader 3.0 beta demo #61
Conversation
This looks great! Without the |
Correct. |
|
Just to get this straight, |
Yes (presuming the configuration is correct). In this example I just put
The existing implementations of both React Transform / React Hot Loader are going away. The new implementation will be branded as React Hot Loader 3, but will internally use a combination of their approaches. It will also not be webpack-specific. “Loader” originally meant a Webpack transform but since it’s a project for “hot reloading” I think it’s fine that we expand the scope, and |
Here is an example repo with jspm/SystemJS used in place of webpack: https://github.com/tyscorp/react-hot-boilerplate/tree/jspm The proxying stuff does not currently work as no exports have It seems like I did experiment with creating |
I added Babel plugin in case you’d like to try it. |
@@ -1,3 +1,10 @@ | |||
{ | |||
"presets": ["es2015", "stage-0", "react"] | |||
"presets": [ | |||
["es2015", {"modules": false}], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/es2015/latest/
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is necessary disable modules? looks like works without this option
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Kikobeats disable modules has no effect on hot loader. Webpack now can handle es 6 modules and for better tree shaking this has to be off in babel.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tracker1 might as well use babel-present-env instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dlebedynskyi agreed, apparently there's a deprecation message on -latest that says as much now.
What would be the correct setup if instead of having a SPA we have an hybrid server rendered page with a bunch of standalone React components rendered independently at different places on the same page. For instance when you just want to add a JS widget (in React) on an existing page. Note that I have a single entry point "main.js" in webpack which works with some kind of a router calling different functions (which render react components) depending on the current URL path. For now, I have to wrap each component in a different along with module.hot.accept stuff. While this makes sense and works fine, it's kind of repetitive when I need to render more than 1 component in the same page. I know that since each component is rendered separately, they are each different mini-application with their own lifecycle. Just wondered if I can do better than this :) |
@benjamindulau i don't know if this is the right place for this discussion, but i'll answer anyway, then if any more info is needed i'd recommend stack overflow rather than adding to the discussion here. sounds like a custom webpack-loader might work here. You can make the loader wrap the files for you. I've only ever had a hand in building one so i don't know best practises, but the reason for mine and yours were very similar. I wrapped each component in code that would render each component within a ruby app, so we could drop in components independently. here is the source to get you started. const loaderUtils = require('loader-utils');
const getComponentName = (componentPath) => {
const componentPathSegments = componentPath.split('/');
//return the second-to-last segment
return componentPathSegments.slice(-2, -1)[0];
};
module.exports = function (source) {
let componentName;
let loaderSource = source;
this.value = loaderSource;
this.cacheable && this.cacheable();
try {
componentName = getComponentName(loaderUtils.getRemainingRequest(this));
}
catch (e) {
return source;
}
try {
loaderSource = `${source};
window.document.addEventListener("DOMContentLoaded", function(event) {
window.setTimeout(function(){
const elems = document.querySelectorAll('[toga=${componentName}]');
[].forEach.call(elems, function(elem) {
let props;
try {
props = JSON.parse(elem.getAttribute('props'));
} catch (e) {
props = {};
}
const Component = (typeof exports.default === 'undefined')
? module.exports
: exports.default;
ReactDOM.render(<Component {...props}/>, elem);
});
}, 1);
});`;
}
catch (e) {
return source;
}
this.value = loaderSource;
return loaderSource;
}; |
For those who are having trouble with react-router 3 + async routes + hot-module-reload, please see: gaearon/react-hot-loader#288 (comment) You may look at https://github.com/moxystudio/react-with-moxy for a working example. |
}, | ||
|
||
plugins: [ | ||
new webpack.optimize.UglifyJsPlugin({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is redundant since webpack -p
will process output via uglify without the plugin configured.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JeremyBernier your solution seems to be working for me, but I get |
); | ||
|
||
render(App); | ||
if (module.hot) module.hot.accept('./App', () => render(App)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gaearon Do you need to re-require the App
before calling render?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 in fact this line should be:
if (module.hot) {
// eslint-disable-next-line global-require
module.hot.accept('./App', () => render(require('./App').default));
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should not, unless you are incorrectly transforming modules before webpack sees them.
You only need to require
or import()
again if you require
d or import()
ed the first time. Static imports are live and are always up-to-date (internally, webpack will re-require it before calling your callback).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kovensky I'm inclined to believe you're wrong due to the official 3.0 docs saying otherwise: https://github.com/gaearon/react-hot-loader/edit/master/docs/README.md#L96
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that is incorrect for webpack 2, as long as you disable the module transform in babel/typescript/etc. webpack has to see the raw import
/ export
commands. The require
is necessary if they are getting converted to require
calls by your preprocessor.
See the webpack 2 section in https://github.com/gaearon/react-hot-loader/blob/master/docs/README.md#webpack-2
Not sure if this is the right forum for the following comments, but I see lots of references to universal rendering projects. I just got universal rendering + [email protected] working together and have some tips.
That is, your publicPath should contain the full URL of your webpack-dev-server otherwise it will try to make the hot module reload request to your backend server instead of the webpack-dev-server. |
@dantesolis dev dependency |
Shouldn't be a dependency since you |
@aymericbouzy you can work around that problem with a // HmrContainer.js
export default (process.env.NODE_ENV === 'development')
? require('react-hot-loader').AppContainer // eslint-disable-line
: ({ children }) => (children); to be used like: // client-entry.js
const App = (
<HmrContainer>
<Root />
</HmrContainer>
); |
if (module.hot) { |
can we merge green? or upgrade to react-hot-loader 4? |
Update README
What is going on here?... |
Nothing. And already for a while. Let's close this as long as React-Hot-Loader v3 is outdated, and React-Hot-Loader v4 is also might sunset soon. |
A Big Update Is Coming
React Hot Loader 3 is on the horizon, and you can try it today. It fixes some long-standing issues with both React Hot Loader and React Transform, and is intended as a replacement for both.
Some nice things about it:
react-hot-loader/babel
from.babelrc
and instead addreact-hot-loader/webpack
to loaders)The docs are not there yet, but they will be added before the final release.
For now, this commit is a good reference to upgrading your project from React Hot Loader 1 to React Hot Loader 3 alpha. Then see another commit as a reference for upgrading from React Hot Loader 3 alpha to React Hot Loader 3 beta.
With lessons learned both from RHL and RT, here is a demo of a unified approach.
This is really undocumented for now, and we might change API later, so feel free to play with it at your own risk. 😉
react-hot-loader/webpack
is intended to be optional. We will provide a complementaryreact-hot-loader/babel
that detects unexported components as well. You will be able to use either, depending on whether you already use Babel or not.Known Issues
AppContainer
crashes (Crashes during server rendering react-hot-loader#283). Until fixed, a workaround is to render the app directly on the server instead.RedboxReact
sometimes fails to display an error message due to TypeError: Line Number must be a Number stacktracejs/stackframe#11.React.createFactory
orReact.DOM.*
factories. It works either with JSX or withReact.createElement
. (Doesn’t work with React.createFactory() react-hot-loader#277)