Webpack-dev-server: watchContentBase watches for the first level only, ignoring deeper folders

Created on 13 Dec 2017  ·  12Comments  ·  Source: webpack/webpack-dev-server

  • Operating System: Windows 10
  • Node Version: 9.2.0
  • NPM Version: 5.5.1
  • webpack Version: 3.10.0
  • webpack-dev-server Version: 2.9.7
  • [x] This is a bug
  • [ ] This is a feature request
  • [ ] This is a modification request

Code

  // webpack.config.js
...
devServer: {
    ...
    contentBase: DEST,
    watchContentBase: true,
    ...
}

Expected Behavior

Setting watchContentBase to true should watch contentBase paths all way deep

Actual Behavior

According to chockidar documentation, setting depth parameter limits the depth of folders being traversed, and the fix of #1208 limits it to 0, leading to changes in the deeper folders being ignored, and not triggering recompilation.

For Bugs; How can we reproduce the behavior?

  1. Place some folder with files and nested structure in the contentBase folder (folder1/folder2/file1.css)
  2. Start webpack-dev-server with watchContentBase: true
  3. Change file1.css from the structure created on step 1.

Most helpful comment

I don't think this person built their use-case around a bug, the documentation for watchContentBase states:

"Tell the server to watch the files served by the devServer.contentBase option. File changes will trigger a full page reload."

I would say that means all files within that folder. I think your fix for #1208 broke this feature. Either bug should be fixed or if this was genuinely an intended feature then the documentation needs to be updated.

All 12 comments

Unfortunately this isn't actually a bug in webpack-dev-server, but designed behavior. WDS uses chokidar and the options that WDS uses for chokidar mirror those found in watchpack, which is what webpack proper uses to watch files.

You'll notice that depth: 0, is defined in the options both here and in watchpack. That's expicitly to prevent complexity issues. Until watchpack, and by extension webpack, decides to change that value, we must keep it the same. You can try petition the folks running watchpack to allow that value to be changed, however.

@creage I'm not sure why you deleted your comment, but I'm happy to respond none-the-less.

@shellscape well, we've built our build process around this feature, and it was fine for around a year, and now it is removed, and you say it is as designed...
Is there any workaround to force webpack-dev-server to watch for nested changes of contentBase? I've tried to define my folders as array, but this does not work for some reason - changes still don't trig recompilation.

Unfortunately you built a solution around a bug that was subsequently fixed. If you'd like your use-case to be supported, bearing in mind that it's intentionally unsupported at the moment, the right path is to petition the watchpack module to allow overriding of the depth property to be set via options passed in. If it changes there, webpack-dev-server will quickly follow suit.

@shellscape after some deeper diving into the code, I understood, that this depth parameter has a great importance. The issue with it (if you don't limit it) is a huge amount of FS watchers, mostly redundant. Setting it to 0 ensures of watching root folder only.

So, I've ended up with writing my custom webpack plugin, which triggers a change event on root folder whenever some of my inner folders updated. Kinda event delegation. Nice approach, I like it more than multiple watchers.

@creage that's great news. please do share your plugin with the community!

I don't think this person built their use-case around a bug, the documentation for watchContentBase states:

"Tell the server to watch the files served by the devServer.contentBase option. File changes will trigger a full page reload."

I would say that means all files within that folder. I think your fix for #1208 broke this feature. Either bug should be fixed or if this was genuinely an intended feature then the documentation needs to be updated.

@creage would you mind sharing your webpack plugin? Also running into this.

@shellscape I believe that @BiggAdd has a valid point here — if only watching root for changes is the intended behavior, I believe the documentation needs to updated to reflect that

@chasegiunta I no longer maintain this project and instead have shifted my focus to https://github.com/webpack-contrib/webpack-serve, which is in many ways superior to webpack-dev-server and allows users to fully control scenarios like this one.

@chasegiunta well, the plugin code is really simple. The idea is every time some paths different then root are updated, I touch some file in the root, which triggers WDS to recompile.

const path = require('path'),
    fs = require('fs');
/**
 * Forces App to reload by touching index.html everytime module is recompiled
 */
class AppWatchPlugin {

    constructor(dest, file) {

        this.dest = dest;

        this.file = file || 'index.html';
    }

    apply(compiler) {
        compiler.plugin('done', () => {

            const currentDate = new Date(),
                fullPathOfFile = path.resolve(this.dest, this.file);

            fs.utimes(fullPathOfFile, currentDate, currentDate, err => {
                if (err) {
                    console.log(err);
                }
            });
        });
    }
}

module.exports = AppWatchPlugin;

@creage FYI, not a good solution change atime and ctime, you can break cache for package which using this files.

Better example:

before(app, server) {
      const chokidar = require("chokidar");
      const files = [
        // Refreshing php files
        "**/*.php"
      ];

      chokidar
        .watch(files, {
          alwaysStat: true,
          atomic: false,
          followSymlinks: false,
          ignoreInitial: true,
          ignorePermissionErrors: true,
          ignored,
          persistent: true
        })
        .on("all", () => {
          server.sockWrite(server.sockets, "content-changed");
        });
    }

Appreciate the time & answers to you both @evilebottnawi & @creage . I was really hopeful I could get one of your solutions to work.

@creage unfortunately, I can't seem to get the plugin to be called after saving a deeper folder.

@evilebottnawi Also tried your solution but ran into issues with globbing (chokidar doesn't seem to like / in the glob path, throws no parsers registered for: "]a(r)" errors)

I feel defeated! Any further suggestions you two have would be welcome 😅

* UPDATE *
Implemented https://github.com/amasad/sane in place of chokidar and it seems to work! 🎉Thanks again for both y'alls help.

@evilebottnawi Thanks! Your solution worked perfectly in my use-case.

My webpack-dev-server + Jekyll setup -

edit: 🤦‍♂️ as it turns out, I didn't need the manual watchers for my use case at all.
contentBase was enough.... but the code still works.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Jack-Works picture Jack-Works  ·  3Comments

hnqlvs picture hnqlvs  ·  3Comments

tulika21-zz picture tulika21-zz  ·  3Comments

MJ111 picture MJ111  ·  3Comments

daryn-k picture daryn-k  ·  3Comments