webpack: Dynamic Contexts don't register for Hot Module Replacement

The following code won’t hot reload (it will log [HMR] Cannot apply update. Need to do a full reload!)

var context = require.context("../../", true, /\.viewtest$/);
var s = context("../../app/screens/categories/view.jsx.viewtest");

if (module.hot) {
  module.hot.accept(["../../app/screens/categories/view.jsx.viewtest"], function (updatedDependencies) {
    console.log("Module reloaded!");
    s = context("../../app/screens/categories/view.jsx.viewtest");
  });
}

but the following code will

var context = require.context("../../", true, /\.viewtest$/); //just to make sure the dynamic context itself isn't what disturbs the HMR

var test = require("../../app/screens/categories/view.jsx.viewtest");

if (module.hot) {
  module.hot.accept(["../../app/screens/categories/view.jsx.viewtest"], function (updatedDependencies) {
    console.log("Module reloaded!");
    require("../../app/screens/categories/view.jsx.viewtest");
  });
}

which means that I have a working HMR setup.

The code seems to be compiled okay:

    var context = __webpack_require__(3);
    var s = context("./app/screens/categories/view.jsx.viewtest");

    if (true) {
      module.hot.accept([5], function (updatedDependencies) {
        console.log("Module reloaded!");
        s = context("./app/screens/categories/view.jsx.viewtest");
      });
    }

It looks like a require going through the context module isn’t hooked into the hot module code. Based on what I understand of HMR this is because the the context module is marked as the parent of the to-be-reloaded module and since it doesn’t accept the reload the module that creates the context must accept it. However, there is no way to say hot.module.accept("dynamic context", cb); or something like that.

Is this a bug or a design choice? If it is a bug: do you have tips for fixing it?

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 16 (4 by maintainers)

Most upvoted comments

for those of you who end up at this issue because you can’t get HMR and require.context to work. I’ve uploaded a minimal working version here: https://github.com/jauco/webpack-hot-module-reload-with-context-example

Only directly required modules can be accepted. A context is like a module so your tree is like this

module  -->  context /\.viewtest$/  -->  ./app/screens/categories/view.jsx.viewtest

So you need to accept the context module:

var context = require.context("../../", true, /\.viewtest$/);
if (module.hot) {
  module.hot.accept(context.id, function() {
    console.log("Module reloaded!");
    context = require.context("../../", true, /\.viewtest$/)
  });
}

I think that jauco/webpack-hot-module-reload-with-context-example@a670b83c8918c60dd6a1eaedea5b2d71fab7ee8d makes it more clear what is happening. A way to get the behaviour you seem to want is shown in jauco/webpack-hot-module-reload-with-context-example@448b5f503c0a8922032f8449ef3e19dd33be3d03

For anyone else who comes along, I had to effectively run this:

// This was the key to it all
fixtures.keys().map((path) => fixtures(path));
module.hot.accept(fixtures.id, () => { ... });