Skip to content

Instantly share code, notes, and snippets.

@markerikson
Last active October 30, 2018 17:36
Show Gist options
  • Save markerikson/8a1053bf0389abc9cc52b18f8c9a1288 to your computer and use it in GitHub Desktop.
Save markerikson/8a1053bf0389abc9cc52b18f8c9a1288 to your computer and use it in GitHub Desktop.
Webpack/HMR reload times and file structure dependency chains

Here's a sample scenario. Let's say we're using a "feature-first" folder structure based in /src, and we're trying to use index.js files to re-export files deeper in the hierarchy as a way of defining a sort of "public API" for a given feature folder. A sample of this might look like:

/features/A/ComponentA.jsx

export default ComponentA = () => (
    <div>Component A</div>
);

/features/A/actions.js

export function doThingForA() {
    console.log("Did a thing for A");
}

/features/A/index.js

export {default as ComponentA} from "./ComponentA";

export {doThingForA} from "./actions";

From there, Feature B might happen to use ComponentA:

/features/B/ComponentB.jsx

import {ComponentA} from "features/A";

export default ComponentB = () => (
    <ComponentA />
);

And Feature C might want to use an action creator from Feature A:

/features/C/ComponentC.jsx

import {connect} from "react-redux";
import {doThingForA} from "features/A";

export const ComponentC = ({doThingForA}) => (
    <button onClick={doThingForA}>Do The Thing</button>
);

export default connect(null, {doThingForA})(ComponentC);

Now both code from Feature B and code from Feature C depend on the root of Feature A, and its re-exports.

So, now if I happen to edit /features/A/actions.js, the dependency chain will include:

  • /features/A/actions.js
    • /features/A/index.js
      • /features/B/ComponentB.jsx
      • /features/C/ComponentC.jsx

And so on. In particular, note that while ComponentC directly referred to the affected function (and therefore should be recompiled and updated), ComponentB didn't actually care about the affected function, but will get recompiled too.

As a result, I'm pretty sure that the re-exports approach winds up increasing the overall dependency chains, and therefore the hot-reload time goes up.

In my own app, the time for Webpack to do an incremental recompile has stayed the same (under 2 seconds), but the time needed to apply those updates on the client has gone up from about 1-2 seconds to close to 20 seconds.

I'll also note that I'm using "plain HMR" only, ie, using module.hot.accept("./app/Root") in my index.js to reload my entire component hierarchy on each change.

20 seconds for hot reload still totally beats a complete rebuild and page reload every time, but it'd be nice if I could work that back down to 3-4 seconds again.

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