Webpack加载器:缓存时是否考虑了选项?

时间:2018-02-26 16:14:11

标签: javascript webpack

我正在编写一个应该可缓存的Webpack加载器。 documentation for this.cacheable说:

  

当输入和依赖关系没有改变时,可缓存的加载器必须具有确定性结果。

现在我想知道:在这个意义上,加载器的选项是否算作“输入”?

假设我有一个Webpack构建,它在模块上使用带有选项{ foo: 1 }的加载器。在下一次编译中,它在同一模块上使用相同的加载器,但使用选项{ foo: 2 }。是否会重新使用第一个编译的输出,或者Webpack(正确)是否意识到加载器的选项已经改变,从而重新加载模块?

假设Webpack 比较options个对象,它们如何比较?引用?使用深度比较?比较逻辑将决定我可以安全地使用什么类型的数据作为加载器选项。

2 个答案:

答案 0 :(得分:1)

简短版:

Webpack通过其request字符串标识模块。此字符串包含文件路径以及所有相关加载器的路径和选项。这实际上意味着更改一个加载器上的选项将导致不同的请求字符串,因此之前的加载结果将不会被重复使用。

长版:

请求字符串是"!" -separated,由this code创建。

考虑这个请求字符串:

"/Users/wolf/dev/webpack-test/test-loader.js!/Users/wolf/dev/webpack-test/patch-loader.js??ref--0-0!/Users/wolf/dev/webpack-test/src/foo.js"

这意味着(从右到左)首先使用带有选项/Users/wolf/dev/webpack-test/src/foo.js的加载器/Users/wolf/dev/webpack-test/patch-loader.js加载文件ref--0-0,然后加载/Users/wolf/dev/webpack-test/test-loader.js而不加任何选项

现在,相关问题是Webpack如何序列化加载器'创建请求字符串时的选项。答案可以找到in this code

loaderData成为此形式的对象:

{
  loader: string, // Path to loader
  options: string | object | null | undefined,
  ident: string | null | undefined
}
  • 如果loaderData.options是一个字符串,则按原样使用。
  • 否则,如果loaderData.ident是真实的,则使用此值。
  • 否则,loaderData.options使用JSON.stringify进行字符串化。

当加载程序specified statically时,Webpack知道他们的选项不会发生变化。因此,RuleSet.normalizeRule()会为其分配固定的ident属性。这就是上面示例中ref--0-0发生的事情。

这里的一个关键见解是加载器选项应该是相当简单的对象,因此在它们上调用JSON.stringify并不会丢失任何信息。否则,Webpack可能会无意中重新使用使用不同加载程序选项的缓存结果。或者,您可以将loaderData.ident显式设置为唯一标识选项的字符串(例如哈希代码)。

答案 1 :(得分:0)

如果您更改了加载程序的输入,那么您实际上是在创建它的新实例,因此它不应该使用带有不同选项的加载程序中的缓存。

如果你看这里,它看起来只是设置一个标志,说明是否要求可缓存,并且由你来缓存结果。无论如何,它总是打电话给你的装载机。 https://github.com/webpack/loader-runner/blob/master/lib/LoaderRunner.js#L270