React Hot Loader 3 #240

Open
wants to merge 173 commits into
from

Projects

None yet
@gaearon
Owner
gaearon commented Apr 17, 2016

Work in progress.
(We are skipping 2 because the approach is way too different from 2 alpha which went nowhere).

Some info here: gaearon/react-hot-boilerplate#61

@gaearon gaearon referenced this pull request in tyscorp/react-transform-jspm-hmr Apr 17, 2016
Closed

Status #2

@nfcampos
Collaborator
nfcampos commented Apr 18, 2016 edited

@gaearon there's a bug with the babel plugin, it thinks variables babel creates to transpile arguments spread should be tagged, see this gist, see _len and _key and args
the issue appears to be it thinks those three variables are in the global scope when they are in fact not
https://gist.github.com/nfcampos/216edf34ae47dfff809df41c58b58c8f

@anaibol
anaibol commented Apr 18, 2016 edited

Asking here because I am not sure to open an issue for..
What's the diference between React Hot Loader and React transform / HMR? I thought that React Hot Loader was dead in favor of React Transform.

@gaearon
Owner
gaearon commented Apr 18, 2016 edited

@anaibol

Thank you for asking! I go over this difference in detail here: https://medium.com/@dan_abramov/hot-reloading-in-react-1140438583bf. The result (React Hot Loader 3) is what I came up with, having learned from both approaches and their weaknesses.

I thought that React Hot Loader was dead in favor of React Transform.

I thought so too 😉

@gaearon
Owner
gaearon commented Apr 18, 2016

@nfcampos Thanks for reporting, should be fixed in -alpha.9.

@gaearon gaearon referenced this pull request in stacktracejs/stackframe Apr 19, 2016
Closed

TypeError: Line Number must be a Number #11

@fardormu fardormu referenced this pull request in 127labs/generator-duxedo Apr 19, 2016
Open

Use React Hot Loader 3 #9

@insin insin referenced this pull request in insin/nwb Apr 20, 2016
Open

React Hot Loader 3 #99

@jcreamer898

@epilande epilande referenced this pull request in epilande/yaris Jul 16, 2016
Open

Set up react hot loader 3 #11

calesce added some commits Jul 27, 2016
@calesce calesce only copy the parameter identifier on the class
properties transform, since the parameters in the source code can
have default values, which don't need to be copied when calling
the new generated method
61c0fa9
@calesce calesce move test into its proper `describe()` block b4e6dd0
@calesce calesce for the class properties transform,
if the class properties function has destructured parameters,
instead of copying the destructuring expression, create new identifiers
for each param, and call the generated method with those new parameters
f474b69
@calesce calesce Change class property transform to use rest params/spread operator
This allows the class property functions to be hot-reloaded properly when
changing the number of arguments
caf6d51
@thecentric

I'm having an issue with this branch when trying to run on Ubuntu 14.04 (working fine for a colleague on OSX).

ERROR in ./src/index.js
Module not found: Error: Cannot resolve module 'react-hot-loader' in /home/demelza/Desktop/react-hot-boilerplate/src
 @ ./src/index.js 3:22-49

Any ideas? I tried a couple of versions of node.

@MoOx
MoOx commented Jul 29, 2016

@thecentric you probably don't have the dependency installed. Try "npm install" if the deps is already specified in your package.json, or "npm install --save-dev react-hot-loader@^3.0.0-beta.2" if not.

@thecentric

@MoOx thanks for your reply, unfortunately that's not working; I can see the package in node_modules so it's definitely installed (I tried the second command you gave anyway, but no luck).

@tsnieman
tsnieman commented Jul 30, 2016 edited

@thecentric Look closely at your error message:

ERROR in ./src/index.js
Module not found: Error: Cannot resolve module 'react-hot-loader' in /home/demelza/Desktop/react-hot-boilerplate/src
@ ./src/index.js 3:22-49

It's only looking for the module in the src directory. I think you need to add node_modules to your module resolution paths.

EDIT. For example, my webpack config has something like this:

module.exports = {
  // Base directory used when resolving the 'entry' option
  context: __dirname,

  resolve: {
    root: __dirname, // ABSOLUTE PATH ONLY
    modulesDirectories: [ // <--- determines where to look for modules.
      "node_modules",
      "src",
    ],
  },

  ...
@thecentric
thecentric commented Aug 1, 2016 edited

Thanks for your comment @tsnieman. I'm actually using react-hot-boilerplate (the next branch). The webpack.config.js has no configuration for the module resolution paths, so I've tried adding your suggested code, and also:

resolveLoader: {
  'fallback': path.resolve(__dirname, "node_modules")
},

but no luck so far. The node_modules directory is in the site root and I think webpack should check there by default. I'm also using the module in a custom project with other node modules that load first; they are importing fine, for some reason it's just react-hot-loader having issues (and only the next branch, and only for my ubuntu machine and an ubuntu VM I tried with; colleagues with OSX are fine).

Strangely we're running an npm build step inside of an ubuntu docker container (during docker image building, not during the running of the container), when building the docker image on my machine the npm build fails (with the same react-hot-loader module import failure), however building the image from a separate container with different base OS (using the docker base image which is Alpine Linux I think) and the npm build is fine. I'm not really sure what to make of that!

@devinrhode2
devinrhode2 commented Aug 3, 2016 edited

How does react-hot-loader relate to redux-devtools? (It looks like maybe redux-devtools is a sort of final solution.)

@kwelch
kwelch commented Aug 3, 2016

What are the limitations of hot loading a functional component?

@Tatones
Tatones commented Aug 8, 2016

Any timeline for releasing this new version? :) Great work on it by the way!

@glenjamin glenjamin referenced this pull request in glenjamin/webpack-hot-middleware Aug 17, 2016
Closed

can this middleware work when modifying stateless component? #126

@inithink
inithink commented Aug 22, 2016 edited

HMR will not work if there was error. (commit: f134ff3)
Step:

  1. in Counter.js, make error and save.
    `return (

    Counter: {this.state.counter}

    dummyErrorString );`
  2. revert it, and change below
    `return (

    Counter1: {this.state.counter}

);`
3. No update will be found.

@manuel-colmenero

Hey there, I think I discovered a bug in this branch. Is this the correct place to report it? Anyways, here it goes...

Using the generic webpack loader (react-hot-loader/webpack) instead of the babel plugin (react-hot-loader/babel) causes a weird issue. The loader returns always the same module if the modules' file names are the same (but the paths are different).

Step 1: Create two modules with different paths but identical filenames:

components/test1/index.js
components/test2/index.js

Step 2: Load those modules from a third one:

import Test1 from "components/test1
import Test2 from "components/test2

Both Test1 and Test2 are the same component, I think the first one that was required:
Test1 === Test2

Otherwise, congratulations on the new version, it rocks!

@ctrlplusb
Contributor

@manuel-colmenero are you sure about this? I have an identical component structure to what you are describing in my projects and haven't had the same issue. I'm using webpack v2 though... not sure if that makes a difference. You can have a look at my project's components here.

@manuel-colmenero
manuel-colmenero commented Aug 22, 2016 edited

I am pretty sure about this, I've been "hunting ghosts" for a few hours until I could reproduce it reliably. I stripped everything down so I'm pretty sure it can't be anything else.

A few differences between your boilerplate and mine are:

  • I use the latest Webpack stable version (1.13.1).
  • I use webpack-dev-server instead of rolling my own dev server.
  • My index.js files are the modules themselves, they're not empty JS files pointing to the actual module.
  • You don't actually use react-hot-loader/webpack but the other one, react-hot-loader/babel, which also works in my setup. This seems to be the issue.

So to clarify things: react-hot-loader/babel (babel plugin, you add it to the babel config) works fine; react-hot-loader/webpack (webpack loader, you have to add it to the webpack config along with babel-loader) does not.

Right now I can't (I'm at work) but when I have time I'll try to put up a repo reproducing the issue.

@AndrewGrachov
AndrewGrachov commented Sep 1, 2016 edited

+1 for non working react-hot-loader/webpack
I use pre-babeled files, and it does not reload

UPD:

Seems to be my curved hands after all.
With code like this

render(
    <AppContainer>
        <Router children={routes} history={browserHistory} />
    </AppContainer>,
    document.getElementById('react-view')
);

if (module.hot) {
    module.hot.accept(() => {
        render(
            <AppContainer>
                <Router />
            </AppContainer>,
            document.getElementById('react-view')
        );
    });
}

Works like a charm

module.hot.accept....

is MANDATORY!!!
No docs say that, found in one of teh threads.

calesce added some commits Sep 3, 2016
@calesce calesce Merge pull request #349 from jameskraus/next-docs
Fixing the broken V3 example in the docs
123d940
@calesce calesce Merge pull request #314 from nathanmarks/fix-redbox-require
Fix RedBox require and add a test
6e7eee7
@calesce calesce Merge pull request #299 from capaj/patch-1
bumped redbox-react dependency
bb7dec3
@calesce calesce Merge pull request #302 from meyer/next
Change `NODE_ENV === production` to `module.hot`
1744629
@calesce calesce 3.0.0-beta.3 ffb5155
@peter-mouland
Contributor

If anyone is interested, I have implemented an example app, react-lego which implements v3. here are the code changes required to get it working.

calesce added some commits Sep 7, 2016
@calesce calesce Bump stage-1 dependency to stage-2
Since the class properties proposal was moved to stage 2
at TC39, we no longer need the stage-1 dependency.
752e32d
@calesce calesce Remove unneeded transforms from babel plugin tests
We only care about what the plugin does, and not about how Babel
transpiles ES2015/class properties transforms. This makes the fixtures
more immediately understandable.
669b9a5
@calesce calesce extend AppContainer class property tests
verifying that the class property transform doesn't break the other
transform and cause components to remount.
698d592
@calesce calesce update stage-1 references to stage-2 28e9332
@Faradey27

@gaearon when you plan to release v3? or maybe to introduce beta version?
is it possible to use hot-reloading for now on large production project without a lot of pain?

@peter-mouland
Contributor

I'm not associated with the project so can't talk for the maintainers, these are just my thoughts

@Faradey27 RHL v3.beta3 is available:
npm i -D react-hot-loader@3.0.0-beta.3

in theory its good to use in a large production website because it should only be used in development... but, It's in Beta, so according to SemVer it may have breaking changes before the final version is released. to find out if more breaking changes are likely before final release we'd have to find out from the guys who are building the project.

I found it quite simple to implement, once I was able to see the changes through the comments, which is why i created the react-lego project and this react-hot-loader branch demonstrating the changes.

@wmertens

Also remember, this is dev-only, so the production application is not
impacted. Basically, if it works for you, go for it!

On Sun, Sep 11, 2016 at 11:36 AM Peter Mouland notifications@github.com
wrote:

I'm not associated with the project so can't talk for the maintainers,
these are just my thoughts

@Faradey27 https://github.com/Faradey27 RHL v3.beta3 is available:
npm i -D react-hot-loader@3.0.0-beta.3

in theory its good to use in a large production website because it should
only be used in development... but, It's in Beta, so according to SemVer it
may have breaking changes before the final version is released. to find out
if more breaking changes are likely before final release we'd have to find
out from the guys who are building the project.

I found it quite simple to implement, once I was able to see the changes
through the comments, which is why i created the react-lego
https://github.com/peter-mouland/react-lego project and this react-hot-loader
branch demonstrating the changes
https://github.com/peter-mouland/react-lego/compare/react-hot-loader.


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
#240 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AADWliDFNnGom56Wix6yKJs5oeRfjWvSks5qo8uXgaJpZM4IJPU9
.

@marshallford

Thanks for the fix! Can a new version be cut from this commit?

Collaborator

Yeah, I want to get #322 in and we can do beta 4.

Collaborator

@marshallford 3.0.0-beta.4 is out!

Nuno Campos and others added some commits Sep 14, 2016
Nuno Campos opt out of class properties transpile on use of arguments, new.target…
… inside
7c78ec8
@calesce calesce Merge pull request #1 from nfcampos/class-props-fix
opt out of class properties transpile on use of arguments, new.target inside
43cb67e
calesce added some commits Sep 15, 2016
@calesce calesce Merge pull request #322 from calesce/class-properties
Add transform to support arrow function class properties
ed84f63
@calesce calesce 3.0.0-beta.4 bc263de
jquense and others added some commits Sep 20, 2016
@jquense jquense fix async arrow functions 2ee9e97
@calesce calesce Prevent the Babel plugin from breaking the output of babel-node (#374)
* prevent the babel plugin from breaking the output of babel-node

the tagger code inserted by the babel plugin at the end of every file is an IIFE, which
happens to break babel-node when it's loaded. by changing it to a
variable declaration (that is still immediately invoked), it works the
same way and doesn't break the plugin.

* comment why we assigned the tagger function to an unused variable
1058ad9
@calesce calesce add async arrow class property test with expression body
also move the async function tests under fixtures/class-properties
1df6650
@calesce calesce update tests 38781b3
@calesce calesce Merge pull request #372 from jquense/fix-async-arrow-func
fix async arrow functions
1fe91c8
@calesce calesce 3.0.0-beta.5 3f97daf
@calesce calesce Update CHANGELOG.md 794c02b
@nfcampos @calesce nfcampos more passing tests for class properties transform 4f34665
@nfcampos @calesce nfcampos added tests for class props with same name as class method 46b0d31
@nfcampos @calesce nfcampos added failing test for static class properties 12f3fdd
@nfcampos @calesce nfcampos opt out of class property transform for static class properties 44f9902
nfcampos and others added some commits Oct 7, 2016
@nfcampos @calesce nfcampos add babel-plugin-transform-class-properties to class-properties babel…
… fixtures

- using only babel-plugin-syntax-class-properties produces invalid output
8fab49e
@calesce calesce Use production patch/AppContainer if no module.hot
Prevents cases where NODE_ENV=test imports the development AppContainer
and patching code. We can leave the NODE_ENV=production check in for
manually opting out. Closes #396.
b4de995
@calesce calesce 3.0.0-beta.6 03687ec
@calesce calesce update CHANGELOG.md 284269f
@MoOx
MoOx commented Oct 14, 2016

I am seeing this message

React Hot Loader: App in /.../web/index.js will not hot reload correctly because index.js uses <App /> during module definition. For hot reloading to work, move App into a separate file and import it from index.js.

Here is my index file

// @todo @ flow
/* eslint-disable import/max-dependencies */

import "react-hot-loader/patch" // HMR react patch
import "babel-polyfill"
import "whatwg-fetch"
import { AppRegistry } from "react-native"
import React, { Component } from "react"
import { AppContainer as HotLoaderWrapper } from "react-hot-loader"
import { Provider as StoreProvider } from "react-redux"

import { hideSplashScreen } from "../src/modules/splash-screen"
import AppRoot from "../src/app/AppRoot"
import createStore from "../src/app/redux/store.js"

const store = createStore()

// react-hot-loader need a class
// eslint-disable-next-line react/prefer-stateless-function
class App extends Component {
  render() {
    // require for correct hot loading
    const AppRouter = require("../src/app/AppRouter/web.js").default

    return (
      <HotLoaderWrapper>
        <StoreProvider store={ store }>
          <AppRoot>
            <AppRouter />
          </AppRoot>
        </StoreProvider>
      </HotLoaderWrapper>
    )
  }
}

// copy all assets
const assets = require.context("./assets", true, /.*/)
assets.keys().forEach(assets)

// app placeholder
const rootTag = document.createElement("div")
rootTag.innerHTML = "..."
document.body.appendChild(rootTag)

// start react app, react-native way
AppRegistry.registerComponent("WynsureGroupAdmin", () => App)

AppRegistry.runApplication("WynsureGroupAdmin", { rootTag: rootTag })
hideSplashScreen()

if (module.hot) {
  module.hot.accept("../src/app/AppRouter/web.js", () => {
    AppRegistry.runApplication("WynsureGroupAdmin", { rootTag: rootTag })
  })
}

That said hot loading works perfectly fine

But this notice was bothering me, so I tried to do what the message said. So I did this

index.js

// @todo @ flow
/* eslint-disable import/max-dependencies */

import "react-hot-loader/patch" // HMR react patch
import "babel-polyfill"
import "whatwg-fetch"
import { AppRegistry } from "react-native"

import { hideSplashScreen } from "../src/modules/splash-screen"

import App from "./App.js"

// copy all assets
const assets = require.context("./assets", true, /.*/)
assets.keys().forEach(assets)

// app placeholder
const rootTag = document.createElement("div")
rootTag.innerHTML = "..."
document.body.appendChild(rootTag)

// start react app, react-native way
AppRegistry.registerComponent("WynsureGroupAdmin", () => App)

AppRegistry.runApplication("WynsureGroupAdmin", { rootTag: rootTag })
hideSplashScreen()

if (module.hot) {
  module.hot.accept("../src/app/AppRouter/web.js", () => {
    AppRegistry.runApplication("WynsureGroupAdmin", { rootTag: rootTag })
  })
}

App.js

// @flow

import React, { Component } from "react"
import { AppContainer as HotLoaderWrapper } from "react-hot-loader"
import { Provider as StoreProvider } from "react-redux"

import AppRoot from "../src/app/AppRoot"
import createStore from "../src/app/redux/store.js"

const store = createStore()

// react-hot-loader need a class
// eslint-disable-next-line react/prefer-stateless-function
class App extends Component {
  render() {
    // require for correct hot loading
    const AppRouter = require("../src/app/AppRouter/web.js").default

    return (
      <HotLoaderWrapper>
        <StoreProvider store={ store }>
          <AppRoot>
            <AppRouter />
          </AppRoot>
        </StoreProvider>
      </HotLoaderWrapper>
    )
  }
}

export default App

No message, but hot loading don't work anymore.

I tried to replace my require().default in App.js by an import, no luck.

I am getting:

[HMR] Cannot apply update. Need to do a full reload!
dev-server.js:34 [HMR] Error: Aborted because 106 is not accepted
Update propagation: 106 -> 355
    at hotApply (http://localhost:8080/web.28ffd53129937380cc7e.js:426:30)
    at hotUpdateDownloaded (http://localhost:8080/web.28ffd53129937380cc7e.js:284:13)
    at hotAddUpdateChunk (http://localhost:8080/web.28ffd53129937380cc7e.js:264:13)
    at webpackHotUpdateCallback (http://localhost:8080/web.28ffd53129937380cc7e.js:8:12)
    at http://localhost:8080/0.21264227de06970aa02b.hot-update.js:1:1

Then full page loading. What am I doing wrong?

@calesce
Collaborator
calesce commented Oct 14, 2016

@MoOx: dumb question since I haven't used React Native recently: Don't they have their own hot-reloading implementation with their own bundler?

For React Router < 4 I have a simple example for reloading route config here. There's a caveat that async routes with require.ensure don't work (#288)

It might be worth opening a new issue here (ideally with a repro project), things can get lost in these big threads. 😄

@MoOx
MoOx commented Oct 14, 2016

@calesce sorry I forget to mention it's code for the web, thanks to react-native-web, aliased to react-native via webpack.

@calesce
Collaborator
calesce commented Oct 14, 2016

@MoOx ah ok, yeah I haven't played with that either. I'll take a look later, have you tested that hot-reloading works with a bare-minimum example? I'm guessing AppRegistry.runApplication gets turned into ReactDOM.render.

@MoOx
MoOx commented Oct 14, 2016

Not sure you have read correctly my comment. It's working when everything is in one file (kind of in the example you posted), but I got a warning this will not work and I should explode into 2 files. But with 2 files, it does not work anymore. So this is confusing :)

calesce and others added some commits Oct 19, 2016
@calesce calesce Add "Known Limitations" doc
This shows some common problems with using RHL 3, along with workarounds (since they don't currently have great solutions)
574a410
@calesce calesce Add System.import section on known limitations
Also, remove the section about transforming ES2015 classes because we
want to fix that soon.
142201d
@hedgerh hedgerh Merge pull request #402 from calesce/known-limitations
Add "Known Limitations" doc
644d4f3
@csillag
csillag commented Oct 21, 2016

Is there an estimation about when will this come out of beta? Thanks.

@calesce
Collaborator
calesce commented Oct 23, 2016

@csillag see v3.0 milestone. No estimates but you can always help 😄

@csillag csillag referenced this pull request in juliancwirko/react-redux-webpack-meteor Oct 23, 2016
Closed

Would you consider updating react-hot-loader? #6

@griffinmichl

Strangely, I have the page refershing without module.hot.accept, but when I add it in, I get the message telling me 'App is up to date' without the changes occurring. Anyone experienced this?

@calesce
Collaborator
calesce commented Oct 26, 2016

@griffinmichl: Yeah I've seen that happen, I'm not sure exactly which cases cause it. Would you mind sharing a minimal project reproducing the issue?

@griffinmichl

Thanks for the offer, but I got it worked out. Didn't realize I had to re-require <App /> inside module.hot.accept's callback. I must have been looking at a bad example or old branch.

@griffinmichl

Something I found really useful for getting this up and running after a lot of struggle (especially with koa 2, which has less up to date webpack middleware): just use the webpack-dev-server cli and configure devServer in your webpack config to proxy API and asset requests to your app server. Ended up being much easier to implement and you don't end up with a bunch of dev vs prod logic in your server.

@peter-mouland
Contributor

@griffinmichl i'd be interested in seeing it with Koa v2, have you an example app for a demo?

calesce added some commits Oct 26, 2016
@calesce calesce Remove deprecations from AppContainer
In the alpha versions of 3.0, AppContainer accepted the child component and
its props as props, but we moved to passing a child in the beta. The beta's been out for a while, and I haven't seen any examples
recently using the alpha examples, so I'd say it's safe to remove these deprecations.
475049f
@calesce calesce add Node >= 4 to package.json "engines" 2ce0b3c
@adailey14 adailey14 referenced this pull request in halt-hammerzeit/webpack-react-redux-isomorphic-render-example Oct 29, 2016
Closed

Would React-hot-loader 3.0 be easy to upgrade to? #14

calesce added some commits Oct 31, 2016
@calesce calesce document migrating from create-react-app
9da8e84
@calesce calesce Update README.md
d2706c6
@akoskm
akoskm commented Nov 5, 2016

@griffinmichl yes, I've seen that happening too. The WDS/HMR messages appeared in the console but the App remained the same. I never removed module.hot.accept, but instead of

module.hot.accept('./components/main', () => { // .. });

I switched to

module.hot.accept(() => { // .. });

and it suddenly started working. Here is the relevant commit from my boilerplate project: akoskm/react-hot-boilerplate@9938a62

Since it started working without the './components/main' it also works when that parameter is present. 😲

calesce added some commits Nov 5, 2016
@calesce calesce update Known Limitations doc
add JSX syntax highlighting and add another workaround for comparing React element types.
61582ed
@calesce calesce Update README.md
8365f09
@sunjay sunjay referenced this pull request in HaskellAcademy/academy Nov 13, 2016
Open

Add react-hot-loader once it stabilizes #45

calesce added some commits Nov 20, 2016
@calesce calesce Merge pull request #257 from gaearon/next-docs
[WIP] Repository Documentation (non-gh-pages)
d360e3a
@calesce @calesce calesce Add environment-specific importing for index.js
This removes a few of the error messages that are only applicable in
development, which saves a few bytes in production builds.
51dae3f
@ntucker
ntucker commented Jan 6, 2017

Whenever I change a module, the console logs say it's updated, but nothing changes. I did some tracking on module updates:

  • Changed module is being executed
  • Component render function is being run
  • However, the module code is still old (changing the console.log message doesn't get reflected).

Is webpack somehow not actually updating the code, but just re-executing the existing modules? (I'm using webpack 1.14.0)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment