如何为 webpack 开发服务器手动触发 watch/reload?

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

我有一个相当简单的 webpack 设置,但有点扭曲。我有几种不同的方法来创建我想要的行为,但我想知道是否有更好的方法(我对 webpack 还是很陌生)。

我有一个基本的 TypeScript/Scss 应用程序,所有 src 文件都存在于 src 目录中。我还有一个组件库包,它是通过单独的构建过程动态生成的(通过 Node 触发)。该包也最终位于 src 目录中(它包含一些 sass 变量和属于 src 的一些其他资产)。这是src/custom-library-bundle。我当前的 webpack 设置通过 CopyWebpackPlugin 将适当的包文件移动到 public (dist) 目录。我的 webpack 开发服务器会按预期监视更改和重新加载。这一切都很完美。

现在轮到我们了。我已经设置了一个存在于其他地方的自定义观察器来观察自定义组件库包的变化。当那里发生变化时,它会触发上面提到的自定义构建过程。这(如预期的那样)修改了 src/custom-library-bundle 目录并在填充包时触发 several watches/reloads。从技术上讲它有效吗?并且行为是预期的,但理想情况下,我可以告诉它等到自定义安装工作是 "done" 并且只有 然后 才会触发 compilation/reload.

呸。这不是一件容易解释的事情。这是一个 webpack 配置,(希望)有助于澄清:

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/')
    ]
  }
}

理想方法: 在我最理想的情况下,我只想手动触发 webpack 开发服务器在我的自定义监视回调中执行它的操作;让它忽略 src/custom-library-bundle 直到我告诉它注意。但是,我似乎找不到办法做到这一点。这可能吗?

替代方法 #1: 我可以忽略 src/custom-library-bundle 目录,将更新的文件移动到 public(不使用 webpack 方法),并且然后在我知道完成时触发重新加载。我不喜欢这个,因为无论我是在观看还是只是在做一次性构建,我都想使用相同的过程(我希望所有内容都在 public 目录中结束,因为 webpack 完成了这项工作,而不是因为我写了一个脚本,在特定情况下把它放在那里)。但是,假设我克服了这个问题,我如何触发开发服务器的浏览器重新加载?这可能吗?

替代方法 #2 这是我倾向于的方法,但感觉像是额外的、不必要的工作。我可以将我的自定义构建过程输出到不同的目录(我的 webpack 设置根本不关心的目录)。构建过程完成后,我可以将所有文件移动到 src/custom-library-bundle,手表将在其中拾取 1 个更改并执行单个 complication/reload。这让我如此接近,但感觉我正在添加一个我不想添加的步骤。

替代方法#3?你能想出更好的方法来解决这个问题吗?

更新(包括版本):

想到的webpack提供的有用的东西是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()

  • 当您想在单个 运行 中构建多个编译且其输出相互独立时,多编译器设置很有用
  • 子编译器允许您设置之间的依赖关系 编译器并使用钩子,它们允许您阻止父级,直到, 比如说,子编译完成了将最新的包发送到 资产
  • DllPlugin 允许您创建一个编辑和 很明显可以产生可以包含模块的块 可以用作尚未构建的编译的依赖项(清单 需要事先制作并传递给他们)
  • 以编程方式 管理你的编译器让你写一个简单的 Node.js 脚本 可以手动完成大部分工作。

如果我没理解错的话,你的 webpack 编译器除了期望它有一些添加到输出资产之外,实际上对你的包没有任何依赖,所以你可以考虑进行多编译器构建。如果这对您不起作用,您可以编写一个简单的插件来创建一个子编译器,该子编译器监视所有组件包依赖项并在更改时将构建的包发送到主编译资产中。最终,正如您自己提到的,您可以编写一个简单的脚本并以编程方式将所有内容编织在一起。所有这些方法都将跟踪构建依赖项卸载到 webpack,因此如果您将编译器置于监视模式,webpack 将在需要更新时保持跟踪。

如果您有兴趣进一步了解子编译器的创建和使用方式,我衷心建议您通读 html-webpack-plugin 插件的源代码。该插件似乎不像您所处理的那样处理相同类型的构建设置,但值得注意的是 HTML 插件使用不属于构建依赖项的文件(源引用中没有任何内容)或取决于用于创建添加到输出的 HTML 文件的 files/templates。

将以下 server.sockWrite 调用添加到您的 after 方法:

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");
    });
  };
}

我从未在文档中找到它,但 webpack 的一位核心开发人员在 a comment on GitHub 中提到了它,所以它有点被认可。