知海

Parser 钩子

webpackjsorg-mainAPI 参考

JavascriptParser Hooks

compiler 中的 parser 实例用于解析 webpack 正在处理的每个模块。parser 是 webpack 中继承自 tapable 的另一个类,提供了各种 tapable 钩子,插件作者可以利用这些钩子来自定义解析过程。

parser 位于 NormalModuleFactory 中,因此需要稍微多做一些工作才能访问到它:

js 复制代码
compiler.hooks.normalModuleFactory.tap("MyPlugin", (factory) => {
  factory.hooks.parser
    .for("javascript/auto")
    .tap("MyPlugin", (parser, options) => {
      // `parser` 提供了许多钩子,下面会详细说明。
      // 这里是一个实际示例,使用 `call` 钩子来检测并警告
      // 开发人员调用的已弃用 API 函数
      // (例如:`myCustomApiFunction()`):
      parser.hooks.call
        .for("myCustomApiFunction")
        .tap("MyPlugin", (expression) => {
          console.warn(
            `Warning: 'myCustomApiFunction' is deprecated. Found call at line ${expression.loc.start.line}.`,
          );
        });
    });
});

compiler 一样,根据钩子类型的不同,也可以使用 tapAsynctapPromise

钩子

parser 暴露了以下生命周期钩子,可以按如下方式访问:

W> 从 webpack 5 开始,hooks 不再可扩展。请使用 WeakMap 来添加自定义钩子。

evaluateTypeof

SyncBailHook

在评估包含自由变量 typeof 的表达式时触发。

  • 钩子参数:identifier
  • 回调参数:expression
js 复制代码
parser.hooks.evaluateTypeof.for("myIdentifier").tap(
  "MyPlugin",
  (expression) =>
    /* ... */
    expressionResult,
);

以下代码会触发 evaluateTypeof 钩子:

js 复制代码
const a = typeof myIdentifier;

以下代码不会触发:

js 复制代码
const myIdentifier = 0;
const b = typeof myIdentifier;

evaluate

SyncBailHook

在评估表达式时调用。

  • 钩子参数:expressionType
  • 回调参数:expression

例如:

index.js

js 复制代码
const a = new MyClass();

MyPlugin.js

js 复制代码
parser.hooks.evaluate.for("NewExpression").tap(
  "MyPlugin",
  (expression) =>
    /* ... */
    expressionResult,
);

表达式类型包括:

  • 'ArrowFunctionExpression'
  • 'AssignmentExpression'
  • 'AwaitExpression'
  • 'BinaryExpression'
  • 'CallExpression'
  • 'ClassExpression'
  • 'ConditionalExpression'
  • 'FunctionExpression'
  • 'Identifier'
  • 'LogicalExpression'
  • 'MemberExpression'
  • 'NewExpression'
  • 'ObjectExpression'
  • 'SequenceExpression'
  • 'SpreadElement'
  • 'TaggedTemplateExpression'
  • 'TemplateLiteral'
  • 'ThisExpression'
  • 'UnaryExpression'
  • 'UpdateExpression'

evaluateIdentifier

SyncBailHook

在评估作为自由变量的标识符时调用。

  • 钩子参数:identifier
  • 回调参数:expression

evaluateDefinedIdentifier

SyncBailHook

在评估作为已定义变量的标识符时调用。

  • 钩子参数:identifier
  • 回调参数:expression

evaluateCallExpressionMember

SyncBailHook

在评估对已成功评估的表达式的成员函数的调用时调用。

  • 钩子参数:identifier
  • 回调参数:expression param

以下表达式会触发此钩子:

index.js

js 复制代码
const a = expression.myFunc();

MyPlugin.js

js 复制代码
parser.hooks.evaluateCallExpressionMember.for("myFunc").tap(
  "MyPlugin",
  (expression, param) =>
    /* ... */
    expressionResult,
);

statement

SyncBailHook

通用钩子,在解析代码片段中的每个语句时调用。

  • 回调参数:statement
js 复制代码
parser.hooks.statement.tap("MyPlugin", (statement) => {
  /* ... */
});

其中 statement.type 可以是:

  • 'BlockStatement'
  • 'VariableDeclaration'
  • 'FunctionDeclaration'
  • 'ReturnStatement'
  • 'ClassDeclaration'
  • 'ExpressionStatement'
  • 'ImportDeclaration'
  • 'ExportAllDeclaration'
  • 'ExportDefaultDeclaration'
  • 'ExportNamedDeclaration'
  • 'IfStatement'
  • 'SwitchStatement'
  • 'ForInStatement'
  • 'ForOfStatement'
  • 'ForStatement'
  • 'WhileStatement'
  • 'DoWhileStatement'
  • 'ThrowStatement'
  • 'TryStatement'
  • 'LabeledStatement'
  • 'WithStatement'

statementIf

SyncBailHook

在解析 if 语句时调用。与 statement 钩子相同,但仅在 statement.type == 'IfStatement' 时触发。

  • 回调参数:statement

label

SyncBailHook

在解析带有 标签 的语句时调用。这些语句的 statement.type === 'LabeledStatement'

  • 钩子参数:labelName
  • 回调参数:statement

import

SyncBailHook

在解析代码片段中的每个 import 语句时调用。source 参数包含导入文件的名称。

  • 回调参数:statement source

以下 import 语句将触发一次该钩子:

index.js

js 复制代码
import _ from "lodash";

MyPlugin.js

js 复制代码
parser.hooks.import.tap("MyPlugin", (statement, source) => {
  // source == 'lodash'
});

importSpecifier

SyncBailHook

在解析每个 import 语句的每个说明符(specifier)时调用。

  • 回调参数:statement source exportName identifierName

以下 import 语句将触发两次该钩子:

index.js

js 复制代码
import _, { has } from "lodash";

MyPlugin.js

js 复制代码
parser.hooks.importSpecifier.tap(
  "MyPlugin",
  (statement, source, exportName, identifierName) => {
    /* 第一次调用
    source == 'lodash'
    exportName == 'default'
    identifierName == '_'
  */
    /* 第二次调用
    source == 'lodash'
    exportName == 'has'
    identifierName == 'has'
  */
  },
);

export

SyncBailHook

在解析代码片段中的每个 export 语句时调用。

  • 回调参数:statement

exportImport

SyncBailHook

在解析每个 export-import 语句时调用,例如:export * from 'otherModule';

  • 回调参数:statement source

exportDeclaration

SyncBailHook

在解析每个导出声明的 export 语句时调用。

  • 回调参数:statement declaration

以下导出语句会触发此钩子:

js 复制代码
export const myVar = "hello"; // 也适用于 var, let
export function FunctionName() {}
export class ClassName {}

exportExpression

SyncBailHook

在解析每个导出表达式的 export 语句时调用,例如 export default expression;

  • 回调参数:statement declaration

exportSpecifier

SyncBailHook

在解析每个 export 语句的每个说明符(specifier)时调用。

  • 回调参数:statement identifierName exportName index

exportImportSpecifier

SyncBailHook

在解析每个 export-import 语句的每个说明符(specifier)时调用。

  • 回调参数:statement source identifierName exportName index

varDeclaration

SyncBailHook

在解析变量声明时调用。

  • 回调参数:declaration

varDeclarationLet

SyncBailHook

在解析使用 let 定义的变量声明时调用。

  • 回调参数:declaration

varDeclarationConst

SyncBailHook

在解析使用 const 定义的变量声明时调用。

  • 回调参数:declaration

varDeclarationVar

SyncBailHook

在解析使用 var 定义的变量声明时调用。

  • 回调参数:declaration

canRename

SyncBailHook

在重命名标识符之前触发,用于确定是否允许重命名。这通常与 rename 钩子一起使用。

  • 钩子参数:identifier
  • 回调参数:expression
js 复制代码
const a = b;

parser.hooks.canRename.for("b").tap(
  "MyPlugin",
  (expression) =>
    // 返回 true 允许重命名
    true,
);

rename

SyncBailHook

在重命名时触发以获取新的标识符。仅当 canRename 返回 true 时,才会调用此钩子。

  • 钩子参数:identifier
  • 回调参数:expression
js 复制代码
const a = b;

parser.hooks.rename.for("b").tap("MyPlugin", (expression) => {});

assign(在解析赋值表达式之前)

SyncBailHook

在解析被赋值的表达式之前解析 AssignmentExpression 时调用。

  • 钩子参数:identifier
  • 回调参数:expression
js 复制代码
a += b;

parser.hooks.assign.for("a").tap("MyPlugin", (expression) => {
  // 这在解析 b 之前调用
});

assign(在解析赋值目标之前)

SyncBailHook

在解析赋值表达式之前解析 AssignmentExpression 时调用。

  • 钩子参数:identifier
  • 回调参数:expression
js 复制代码
a += b;

parser.hooks.assign.for("a").tap("MyPlugin", (expression) => {
  // 这在解析 a 之前调用
});

typeof

SyncBailHook

在解析标识符的 typeof 时触发。

  • 钩子参数:identifier
  • 回调参数:expression

call

SyncBailHook

在解析函数调用时调用。

  • 钩子参数:identifier
  • 回调参数:expression
js 复制代码
eval(/* something */);

parser.hooks.call.for("eval").tap("MyPlugin", (expression) => {});

callMemberChain

SyncBailHook

在解析对象成员函数调用时触发。

  • 钩子参数:objectIdentifier
  • 回调参数:expression, properties
js 复制代码
myObj.anyFunc();

parser.hooks.callMemberChain
  .for("myObj")
  .tap("MyPlugin", (expression, properties) => {});

new

SyncBailHook

在解析 new 表达式时调用。

  • 钩子参数:identifier
  • 回调参数:expression
js 复制代码
new MyClass();

parser.hooks.new.for("MyClass").tap("MyPlugin", (expression) => {});

expression

SyncBailHook

在解析表达式时调用。

  • 钩子参数:identifier
  • 回调参数:expression
js 复制代码
const a = this;

parser.hooks.expression.for("this").tap("MyPlugin", (expression) => {});

expressionConditionalOperator

SyncBailHook

在解析 ConditionalExpression(例如 condition ? a : b)时调用。

  • 回调参数:expression

program

SyncBailHook

获取代码片段的抽象语法树(AST)。

  • 参数:ast comments

帮助我们改进文档

发现翻译问题或内容错误?请告诉我们。