postcss/postcss-mixins

Hot reloading of functional mixins does not work

andgra opened this issue · 3 comments

There are 2 issues:

  1. Cached require calls
  2. Sub-dependencies of the mixin files are not passed to the build tools like webpack (via helpers.result.messages)

1:
According to this line:
mixins[name] = { mixin: require(path), file: path }
Function mixins are loaded using node require function. In development mode, this code might be called several times when the source code of function mixin is changed.
But after the first load, required files will not be updated because of the require caching.

One solution would be to clear cached modules. Like this:

mixins[name] = { mixin: require(path), file: path }
delete require.cache[require.resolve(path)]

But if we take into the account the case when mixin has its own dependencies, we have to clear the cache for them too:

mixins[name] = { mixin: require(path), file: path }
let clearModuleCacheRecursively = (module) => {
  module.children.forEach(childModule => clearModuleCacheRecursively(childModule))
  delete require.cache[module.id]
}
let module = require.cache[require.resolve(path)]
if (module) {
  clearModuleCacheRecursively(module)
}

2:
To fix the second issue, we just have to add each child dependency to the watch list alongside with clearing the cache.
Something like this:

mixins[name] = { mixin: require(path), file: path }
let clearModuleCacheRecursively = (module, helpers) => {
  let moduleId = module.id
  module.children.forEach(childModule => {
    helpers.result.messages.push({
      type: 'dependency',
      file: childModule.id,
      parent: moduleId
    })
    clearModuleCacheRecursively(childModule, helpers)
  })
  delete require.cache[moduleId]
}
let module = require.cache[require.resolve(path)]
if (module) {
  clearModuleCacheRecursively(module, helpers)
}

Another, "in-place", solution would be to create a custom postcss plugin that will do these steps after the main plugin as it is. But this solution looks like a hack.

I can create a PR with these changes.

ai commented

Yes, this looks like very useful feature. I am scary to implement it by my own. Waiting for PR.

ai commented

Can we close it?

Yes, thank you