Repository navigation
Watcher doesn't see a new file until restart #6262
Description
Activity
This is caused by the "unsafe" resolver cache. You can disable the cache with
resolve.unsafeCache: falsebut this has very negative impact on performance.Is there any middle ground or a heuristic we could use? For example, if a file is not found, then invalidate any cache entries around it on any FS event.
Reacted by Prateek Jain, Ihor Yemets, Brenton Partridge, Chang Wang and Rhys van der WaerdenThis seems to be the same root issue as #5523, and we're running into it as well when gradually refactoring a codebase (in our case, the watcher starts reporting ENOENT when you rename x.js to x.ts or similar).
It seems that this is where the cache entry is saved (the
resolve.unsafeCachesetting is what determines thecachePredicate):webpack/lib/NormalModuleFactory.js
Lines 239 to 240 in f352436
if(module && this.cachePredicate(module)) { dependencies.forEach(d => d.__NormalModuleFactoryCache = module); And the cache entry is read here:
webpack/lib/NormalModuleFactory.js
Lines 214 to 216 in f352436
const dependencies = data.dependencies; const cacheEntry = dependencies[0].__NormalModuleFactoryCache; if(cacheEntry) return callback(null, cacheEntry); Perhaps one way to achieve this with a minimal performance overhead would be to have a synchronous plugin tap immediately after a cache entry is read or created? Then a new plugin, only enabled during dev (and perhaps enabled by default?), could then:
- run an asynchronous NodeFileWatcher
- maintain a weak trie of the cache entries
- mark parts of that trie as invalidated when a filesystem change is detected
- quickly check the trie synchronously before returning a module from cache (i.e. "check-cache-entry-validity" as a plugin tap point)
This way you wouldn't need to completely turn off the caching, and overhead would be minimal - no need to go out to every resolver out there. And once the API hooks are inserted, the proposed plugin could be developed in a separate repository to meet all these edge cases, so that ongoing webpack core development isn't affected.
Am I missing anything here? Any reason not to try this approach?
Also suffering from this issue at present while slowly migrating from JS to TS. Branch changes are particularly annoying as they nearly always involve renames. I tried to
unsafeCache: falseand it didn't appear to work (although I'm not sure if this might be a symptom of other plugins or configuration).I may be wrong but looks like next PR should fix this #6451
would be nice to get some confirmation of my guess from core team/major contributors..
Actually after spending few hours on this, I'm quite sure unsafeCache option is actually in both resolve and in module section of configuration. Second place is undocumented.
At least for v3.x,
class NormalModuleFactory extends Tapable { constructor(context, resolvers, options) { super(); this.resolvers = resolvers; this.ruleSet = new RuleSet(options.rules || options.loaders); this.cachePredicate = typeof options.unsafeCache === "function" ? options.unsafeCache : Boolean.bind(null, options.unsafeCache);`
And it can be actually a function and then it is a predicate.
Maybe I'm not aware of sth, otherwise it's quite confusing in the docs, I can create a PR if it's the case ?same issue here
I am going to hop on the train and mention it really slows down my developement since no changes detected causes the need to restart and open new server for my react-app each time I run into this.
webpack 5 has this problem fixed
In webpack 5 it's not fixed when using multiple aliases #10015
Reacted by Ramin Rezaei and Geunbae@gaearon @minimit we have the same issue when using multiple aliases
it's getting worked on webpack 5 #9802 (comment)
Reacted by niusealeoShould work with
webpack@next. Feel free to report new issue with reproducible repo.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Do you want to request a feature or report a bug?
Bug.
What is the current behavior?
Consider this project:
package.json{ "scripts": { "start": "webpack --watch src/index.js dist/bundle.js" }, "devDependencies": { "webpack": "^3.10.0" } }src/index.jssrc/x.jsThen do this series of steps:
npm install.npm start.src/x.js.src/xfolder.src/x/index.jswith same content assrc/x.jsused to have.What is the expected behavior?
Webpack recovers from a "not found" error. At the very least after re-saving either
src/index.jsorsrc/x/index.js.Actual behavior is that Webpack gets stuck insisting
./xis not found, and the only way to fix it is by restarting the watcher.Please mention other relevant information such as the browser version, Node.js version, webpack version and Operating System.
OS X Sierra, Node 8.9.1 (but it's an old issue, existed at least since 2016 react/create-react-app#1164).
I couldn't figure out how to correctly set up Webpack beta so I didn't test that.