我正在编写一个插件,对于特定的模块,它会尝试执行在构建时生成的模块,以便将结果保存到json文件中。
为此,我正在点击compilation.hooks.succeedModule
,它会收到一个已构建的NormalModule
对象。然后我试图评估源替换像__webpack_public_path__
这样的webpack变量。
虽然它有点有用,但这种方法感觉非常错误。就像我错过了一些东西。
是否有一种很好的方法可以在构建时从具有__webpack_public_path__
等基本访问权限的NormalModule对象执行模块?也许Webpack提供了更好的方法来做这些事情?
答案 0 :(得分:1)
好的,是的,听起来你可以用另一种方式解决这个问题,我已经完成了类似的工作,我需要更改模块输出,将内容写入磁盘,触发副作用等等。这听起来像你想要的加载器而不是插件。 run-loader
(https://www.npmjs.com/package/webpack-run-loader)执行它加载的模块并导出或返回结果。
您可以编写一个自定义加载器,链接到responsive-loader
和run-loader
之后运行,并从run-loader
接收JSON并将其写入您想要的磁盘(如副作用),然后返回一个空字符串,以便没有任何内容添加到构建中。最终结果是,在您的应用中需要此模块会创建您的图像文件(通过responsive-loader
),并将JSON写入您需要的磁盘(通过自定义加载程序)。或者,您可以跳过run-loader
并在自定义加载器中使用正则表达式从responsive-loader
的输出中获取JSON。在项目依赖项生成的代码上使用正则表达式似乎很脆弱,但只要你的依赖项版本被锁定,它就可以在实践中运行得很好,而且在概念上比向管道添加run-loader
更简单一些。
如果您正在编写webpack插件,我想您也很乐意编写加载器,但如果不是,那么它们非常简单 - 只是一个接受来自之前加载器的源代码的函数它返回代码,并在两者之间做任何你想做的事情。这些文档对API来说并不坏,但是查看一些已发布的加载器的来源也很有帮助。它可能看起来粗略(只是从记忆中吐出来),如:
// img-info-logging-loader.js
// regex version, expects source arg to be output of responsive-loader
import * as fs from 'fs';
export const imgInfoLoggingLoader = (source) => {
const jsonFinderRegex = /someregexto(match)onsource/;
const desiredJSON = source;
const matchArr = jsonFinderRegex.exec(desiredJSON);
if (!matchArr[1]) {
throw new ReferenceError('json output not found in loader source.');
} else {
const imgConfigJsonString = matchArr[1];
// you would write a fn to generate a filename based on the
// source, or based on the module's filename, which is available
// via the webpack loader api
const fileNameToWrite = getFileNameTowrite();
try {
// async might be preferable depending on your webpack
// performance needs
fs.writeFileSync(fileNameToWrite, imgConfigJsonString);
} catch (err) {
throw new Error(`error writing ${fileNameToWrite}`);
}
}
// what the loader inserts into your JS asset: empty string
return '';
}
编辑: 因为根据你的评论你想要输出一个包含所有图像信息的JSON对象,你会想要一个稍微不同的方法来使用插件(这是我所知道的最优雅的方式,可能有其他)。据我所知,插件是做某事的唯一方法。当webpack完成加载模块时。
responsive-loader
的输出中提取JSON,如上所述。但是,它不会将每个写入磁盘。相反,您的加载器将在以下模块上调用方法:json-collector.js
,它只是一个小节点模块,您将用它来保持您正在构建的JSON对象。这一点很尴尬,因为它与加载器分开,但加载器需要它。但是,这个收集器模块很简单,如果你想要更干净,你可以将它变成一个更通用的模块,并将其视为一个适当的,独立的节点依赖。它只是一个带有添加JSON数据的方法的对象,它将它附加到内部JSON对象,还有一个用于读取收集的数据,该数据返回JSON。json-collector
上的方法,从中获取JSON对象并将其写入光盘。 这个解决方案并不适合webpack中的独立插件/独立加载器约定,但如果这并不困扰你,它实际上非常简单,这三个部分中的每一个都有一个简单的工作要做。我已经多次使用过这种模式,它对我有用。