我正在编写一个代码分析webpack插件,希望在webpack包中找到函数名的所有实例。
我为这个问题做了一个回购:https://github.com/RonPenton/webpack-parser-fail-demo
所以解析器非常简单,只是看起来像这样:
class ParsePlugin {
apply(compiler) {
compiler.plugin('compilation', function (compilation, data) {
data.normalModuleFactory.plugin('parser', function (parser, options) {
parser.plugin(`call $findme`, function (expr) {
console.log("found $findme!");
});
});
});
}
https://github.com/RonPenton/webpack-parser-fail-demo/blob/master/parse.js
我想要做的就是在代码中找到$ findme()的所有实例并记录有关它们的信息。稍后,我甚至可能最终改变电话,但这是另一天。
当我提供此源文件时,一切都很顺利:https://github.com/RonPenton/webpack-parser-fail-demo/blob/master/good.js
$findme("Testing");
$findme("Testing too...");
当我运行webpack时,输出显示找到了两个实例:
found $findme!
found $findme!
Hash: a6555af5036af17d9320
Version: webpack 3.6.0
Time: 69ms
Asset Size Chunks Chunk Names
good.js 2.52 kB 0 [emitted] main
[0] ./good.js 47 bytes {0} [built]
但是当我使用不同的入口点时,函数在本地(https://github.com/RonPenton/webpack-parser-fail-demo/blob/master/bad.js)或外部模块(https://github.com/RonPenton/webpack-parser-fail-demo/blob/master/bad2.js)中定义,突然解析器停止查找这些方法。
function $findme(input) {
console.log(input);
}
$findme("Testing");
$findme("Testing too...");
====
import { $findme } from './findme';
$findme("Testing");
$findme("Testing too...");
那是什么交易?我试着深入研究webpack源代码,据我所知,这似乎是故意的。但实际上并没有关于为什么以这种方式完成的文档,而不是即将发表的评论。
这不是可以通过插件完成的吗?
提前感谢您的帮助。
答案 0 :(得分:0)
奇怪的是,当你的函数以某种方式被调用或检索时,webpack 解析器只会调用这些钩子。这就是为什么您的钩子在以一种方式调用函数时起作用,但在从某处导入时不起作用的原因。
我试图找到对一个对象方法的所有调用,但遇到了同样的问题。
另一个人提出的这个github问题更详细:https://github.com/webpack/webpack/issues/9480
要解决这个问题,您需要欺骗 webpack Parser 使其认为由于某种原因它不想调用钩子的函数/方法调用是标识符,就像这里所做的那样:https://github.com/aurelia/webpack-plugin/blob/9f6f7983312c66f857e79b744e4ec257cc287b8b/dist/InlineViewDependenciesPlugin.js
您需要使用解析器 'evaluate' 钩子返回一个自定义 BasicEvaluatedExpression
实例,该实例的 isIdentifier
设置为 true 以用于您要查找的所有函数调用。然后将使用完整的表达式调用 call
钩子。就我而言,我需要包含函数及其参数的完整 CallExpression。