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?

Author: Fantashit

2 thoughts on “Dynamic Contexts don’t register for Hot Module Replacement

  1. 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$/)
      });
    }

Comments are closed.