Hot reloading with create-react-app without ejecting 🔥 ⏏️

…and without react-app-rewired.

Brian Han
Feb 27, 2018 · 3 min read
Very awesome but way-too-serious photo for this article because I guess the theme is “hot”? So, like “fire”? Aziz Acharki on Unsplash

With a few lines of code, you can setup a new create-react-app project with hot-module-replacement (HMR).

Spin up a new react app withnpx create-react-app your-new-app and update the index.js file and voila (see the gist below).

Gist from Charlie Gleason’s post on “Hot Reloading + create-react-app"

But what if I start adding other react things?

  • react-router-dom
  • redux
  • react-redux

Suddenly, HMR doesn’t work when I wrap my App with Provider and BrowserRouter.

I googled around for clues and found my aha moment in the create-react-app github issues:

I tweaked my code accordingly and now my app works with HMR functioning correctly. See with the gists below.

That’s it.

You can stop reading now.

The rest of this article is a bunch of crazy notes because I feel terrible about not knowing how any of this stuff works. The “webpack-layer” is magic to me and I’d like to understand it better. It’s the off-chance that you’ll continue reading that motivates me to write anything at all. SO even though these are notes for myself…thanks for reading and hope you get something out of this.

There’s a “webpack-shaped” hole in my brain

Oh, you’re still here? Alright..well…

I’m going to allow my webpack-noobness to show a little: I don’t know webpack well enough to work with it directly. I do my best to avoid ejecting my projects that use create-react-app. Apologies if this offends anyone but 🤷‍♂️

Even though I have HMR playing nicely with everything else, now I get to use the code I have to understand what’s going on under-the-hood.

Attempting to understand

This module.hot code seems to be the thing — I think it’s a webpack thing.
I’m going to go read these docs and these docs. I’ll update this later with some better written thoughts. Here’s a donut 🍩, enjoy!

API

The API for module.hot looks like it’s short and sweet.

if (module.hot) {
module.hot.accept('./library.js', function() {
// Do something with the updated library module...
})
}
  • Check if there are any spicy modules
  • accept them spicy mods
  • do something in the callback with that module

This makes sense so far…App should be accepted, and we get the updated App component and render it with ReactDOM.render in the callback.

if (module.hot) {  
module.hot.accept('./App', () => {
const NextApp = require('./App').default;
// render with new App here
});
}

But a few things are still weird to me:

  1. Why is it okay to give module.hot.accept a string like, './App'?
    My guess here is that something is happening under the hood that’s resolving the string './App' to the actual App component. Or it’s some reference?
  2. What the heck is require('./App').default?
    This exchange on stackoverflow is the closest thing I can find to an answer, so I’ll need to dig into this a little more.

Other cool stuff

Ejecting create-react-app reveals the webpack config files.

One thing to note is that there’s a custom dev client being used:

{
entry: [
require.resolve('react-dev-utils/webpackHotDevClient'),
],
}

There’s also a comment that explains that this basically replaces this code but with added features for better dev experience, like error display:

require.resolve(‘webpack-dev-server/client’) + ‘?/’, require.resolve(‘webpack/hot/dev-server’),

Links

Brian Han

Written by

Brian Han

UX Developer @ Indeed // Previously: Accenture, IBM, Carbon Design System

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade