amlyhamm
amlyhamm

Reputation: 1150

How to manually trigger watch/reload for webpack dev server?

I have a fairly simple webpack set up with a bit of a twist. I have a few different ways I can think of to create my intended behavior, but I'm wondering if there are better approaches (I'm still fairly new to webpack).

I have a basic TypeScript/Scss application and all of the src files exist in a src directory. I also have a component library bundle that's dynamically generated through a separate build process (triggered via Node). This bundle also ends up in the src directory (it contains some sass variables and a few other assets that belong in src). This is src/custom-library-bundle. My current webpack set up moves the appropriate bundle files to a public (dist) directory via the CopyWebpackPlugin. My webpack dev server watches for changes and reloads as expected. This all works beautifully.

Now for the twist. I've set up a custom watcher that exists elsewhere to watch for the custom component library bundle changes. When a change occurs there, it triggers that custom build process mentioned above. This (as expected) modifies the src/custom-library-bundle directory and sets off several watches/reloads as the bundle is populated. Technically it works? And the behavior is expected, but ideally, I could tell it to wait until the custom installation work is "done" and only then have it trigger the compilation/reload.

Phew. This isn't an easy one to explain. Here's a webpack config that will (hopefully) help clarify:

devServer: {
  contentBase: path.join(__dirname, 'public'),
  port: 9000,
  host: '127.0.0.1',
  after: (app, server) => {
    new MyCustomWatcherForOtherThings().watch(() => {
      // invoked after the src/custom-library-bundle is done doing its thing (each time)
      // now that I know it's done, I want to trigger the normal compilation/reload
    })
  },
  watchOptions: {
    ignored: [
      /node_modules/
      // I've been experimenting with the ignored feature a bit
      // path.resolve(__dirname, 'src/custom-library-bundle/')
    ]
  }
}

Ideal Approach: In my most ideal scenario, I want to just manually trigger webpack dev server to do its thing in my custom watch callback; have it ignore the src/custom-library-bundle until I tell it to pay attention. I can't seem to find a way to do this, however. Is this possible?

Alternate Approach #1: I could ignore the src/custom-library-bundle directory, move the updated files to public (not utilizing the webpack approach), and then trigger just a reload when I know that's complete. I don't love this because I want to utilize the same process whether I'm watching or just doing a one-off build (I want everything to end up in the public directory because webpack did that work, not becuase I wrote a script to put it there under specific scenarios). But, let's say I get over that, how can I trigger a browser reload for the dev server? Is this possible?

Alternate Approach #2 This is the one I'm leaning towards but it feels like extra, unnecessary work. I could have my custom build process output to a different directory (one that my webpack set up doesn't care about at all). Once the build process is complete, I could move all the files to src/custom-library-bundle where the watch would pick up 1 change and do a single complication/reload. This gets me so close, but feels like I'm adding a step I don't want to.

Alternate Approach #3? Can you think of a better way to solve this?

Update (including versions):

Upvotes: 4

Views: 4789

Answers (2)

joemaller
joemaller

Reputation: 20616

Add the following server.sockWrite call to your after method:

devServer: {
  after: (app, server) => {
    new MyCustomWatcherForOtherThings().watch(() => {
      // invoked after the src/custom-library-bundle is done doing its thing (each time)
      // now that I know it's done, I want to trigger the normal compilation/reload

      // calling this on `server` triggers a full page refresh
      server.sockWrite(server.sockets, "content-changed");
    });
  };
}

I've never found this in the documentation, but one of webpack's core devs mentioned it in a comment on GitHub, so it's sort of sanctioned.

Upvotes: 11

Filip Dupanović
Filip Dupanović

Reputation: 33690

Useful things that webpack provides that come to mind are multi-compiler builds, creating a child compiler from a Compiler or Compilation instance, the DllPlugin and programmatically managing the compiler by calling webpack.watch() or webpack.compile().

  • the multi-compiler setup is useful when you want to build several compilations in a single run whose outputs are independent of each other
  • the child compilers allows you to set up dependencies between compilers and using hooks they allow you to block the parent until, say, the child compilation finished emitting the latest bundle into the assets
  • the DllPlugin allows you to create a compilation and it's manifest that could produce chunks that can contain modules that can be used as dependents for yet unbuilt compilations (the manifest needs to be produced and passed to them beforehand)
  • programmatically managing you compiler lets you write a straightforward Node.js script that could accomplish most of this manually.

If I understood correctly, your webpack compiler doesn't really have any dependencies on your bundle aside from expecting it to have something added to the output assets, so you might consider doing a multi-compiler build. If that doesn't work for you, you can write a simple plugin that creates a child compiler that watches all the component bundle dependencies and emits the built bundle into the main compilation assets on changes. Ultimately, as you mentioned yourself, you could write a simple script and programmatically weave everything together. All of these approaches offload tracking build dependencies to webpack, so if you put the compilers into watch mode webpack will keep track when something needs updating.

If you're interested in taking a closer look at how child compilers are created and used, I would heartily recommend reading through the sources of the html-webpack-plugin plugin. It doesn't seem like the plugin is handling the same kind of build setup as you have, but worth noting is that the HTML plugin works with files that aren't part of the build dependencies (nothing in the sources references or depends on the files/templates that are used for creating the HTML files that are added to the output).

Upvotes: 1

Related Questions