阅读(1944) 赞(7)

Webpack:JavascriptParser Hooks

2023-05-11 09:26:25 更新

​parser​ 实例,在 ​compiler​ 中被发现,是用来解析由 webpack 处理过的每个模块。​parser​ 也是扩展自 ​tapable​ 的 webpack 类 并且提供多种 ​tapable​ 钩子,

以下示例中,​parser​ 位于 NormalModuleFactory 中,因此需要调用额外钩子 来进行获取:

compiler.hooks.normalModuleFactory.tap('MyPlugin', (factory) => {
  factory.hooks.parser
    .for('javascript/auto')
    .tap('MyPlugin', (parser, options) => {
      parser.hooks.someHook.tap(/* ... */);
    });
});

和 ​compiler​ 用法相同,取决于不同的钩子类型, 也可以在某些钩子上访问 ​tapAsync​ 和 ​tapPromise​。

钩子

以下生命周期钩子函数,是由 ​parser​ 暴露,可以通过如下方式访问:

evaluateTypeof

SyncBailHook

当对自由变量使用 ​typeof​ 表达式进行求值时触发

  • Hook Parameters: ​identifier​
  • Callback Parameters: ​expression​
parser.hooks.evaluateTypeof
  .for('myIdentifier')
  .tap('MyPlugin', (expression) => {
    /* ... */
    return expressionResult;
  });

这会触发 ​evaluateTypeof​ 钩子的调用:

const a = typeof myIdentifier;

这不会触发:

const myIdentifier = 0;
const b = typeof myIdentifier;

evaluate

SyncBailHook

在求值表达式时调用

  • Hook parameters: ​expressionType​
  • Callback parameters: ​expression​

示例:

index.js

const a = new String();

MyPlugin.js

parser.hooks.evaluate.for('NewExpression').tap('MyPlugin', (expression) => {
  /* ... */
  return expressionResult;
});

表达式的类型:

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

evaluateIdentifier

SyncBailHook

当评估一个自由变量的标识符时调用

  • Hook Parameters: ​identifier​
  • Callback Parameters: ​expression​

evaluateDefinedIdentifier

SyncBailHook

当评估一个已定义变量的标识符时调用

  • Hook Parameters: ​identifier​
  • Callback Parameters: ​expression​

evaluateCallExpressionMember

SyncBailHook

当对已成功求值的表达式调用成员函数时调

  • Hook Parameters: ​identifier​
  • Callback Parameters: ​expression​ ​param​

将会触发钩子的表达式:

index.js

const a = expression.myFunc();

MyPlugin.js

parser.hooks.evaluateCallExpressionMember
  .for('myFunc')
  .tap('MyPlugin', (expression, param) => {
    /* ... */
    return expressionResult;
  });

statement

SyncBailHook

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

  • Callback Parameters: ​statement​
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'​ 时触发

  • Callback Parameters: ​statement​

label

SyncBailHook

当解析带标签的语句时调用此钩子。这些语句的类型为 ​​statement.type === 'LabeledStatement'​​

  • Hook Parameters: ​labelName​
  • Callback Parameters: ​statement​

import

SyncBailHook

在代码片段中每个导入语句都会调用此钩子。​source​ 参数包含所导入文件的名称

  • Callback Parameters: ​statement​ ​source​

The following import statement will trigger the hook once:

index.js

import _ from 'lodash';

MyPlugin.js

parser.hooks.import.tap('MyPlugin', (statement, source) => {
  // source == 'lodash'
});

importSpecifier

SyncBailHook

对于每个​import​语句中的每个指定符,都会调用此钩子函数

  • Callback Parameters: ​statement​ ​source​ ​exportName​ ​identifierName​

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

index.js

import _, { has } from 'lodash';

MyPlugin.js

parser.hooks.importSpecifier.tap(
  'MyPlugin',
  (statement, source, exportName, identifierName) => {
    /* First call
    source == 'lodash'
    exportName == 'default'
    identifierName == '_'
  */
    /* Second call
    source == 'lodash'
    exportName == 'has'
    identifierName == 'has'
  */
  }
);

export

SyncBailHook

该钩子函数会在代码片段中的每个 export 语句被解析时触发

  • Callback Parameters: ​statement​

exportImport

SyncBailHook

在代码片段中的每个导出导入语句(例如:export * from 'otherModule';)都会调用该钩子

  • Callback Parameters: ​statement​ ​source​

exportDeclaration

SyncBailHook

每个导出声明的导出语句都会调用此钩子

  • Callback Parameters: ​statement​ ​declaration​

这些导出语句会触发该钩子函数:

export const myVar = 'hello'; // also var, let
export function FunctionName() {}
export class ClassName {}

exportExpression

SyncBailHook

被用于解析并评估代码中的导出表达式,例如 export default expression;,在导出表达式时触发此钩子

  • Callback Parameters: ​statement​ ​declaration​

exportSpecifier

SyncBailHook

该钩子会为每个导出语句的每个成员说明符调用

  • Callback Parameters: ​statement​ ​identifierName​ ​exportName​ ​index​

exportImportSpecifier

SyncBailHook

该钩子将在每个导出-导入语句的每个成员说明符上触发

  • Callback Parameters: ​statement​ ​source​ ​identifierName​ ​exportName​ ​index​

varDeclaration

SyncBailHook

解析变量声明时触发

  • Callback Parameters: ​declaration​

varDeclarationLet

SyncBailHook

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

  • Callback Parameters: ​declaration​

varDeclarationConst

SyncBailHook

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

  • Callback Parameters: ​declaration​

varDeclarationVar

SyncBailHook

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

  • Callback Parameters: ​declaration​

canRename

SyncBailHook

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

  • Hook Parameters: ​identifier​
  • Callback Parameters: ​expression​
var a = b;

parser.hooks.canRename.for('b').tap('MyPlugin', (expression) => {
  // returning true allows renaming
  return true;
});

rename

SyncBailHook

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

  • Hook Parameters: ​identifier​
  • Callback Parameters: ​expression​
var a = b;

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

assigned

SyncBailHook

会在解析 ​AssignmentExpression​ 时,在解析被赋值的表达式之前触发

  • Hook Parameters: ​identifier​
  • Callback Parameters: ​expression​
a += b;

parser.hooks.assigned.for('a').tap('MyPlugin', (expression) => {
  // this is called before parsing b
});

assign

SyncBailHook

会在解析 ​AssignmentExpression​ 时,在解析赋值的表达式之前触发

  • Hook Parameters: ​identifier​
  • Callback Parameters: ​expression​
a += b;

parser.hooks.assigned.for('a').tap('MyPlugin', (expression) => {
  // this is called before parsing a
});

typeof

SyncBailHook

当解析标识符的​ typeof​ 操作符时触发

  • Hook Parameters: ​identifier​
  • Callback Parameters: ​expression​

call

SyncBailHook

在解析函数调用时被调用

  • Hook Parameters: ​identifier​
  • Callback Parameters: ​expression​
eval(/* something */);

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

callMemberChain

SyncBailHook

当解析对象的成员函数的调用时触发

  • Hook Parameters: ​objectIdentifier​
  • Callback Parameters: ​expression​​ properties​
myObj.anyFunc();

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

new

SyncBailHook

该钩子在解析 ​new​ 表达式时被调用

  • Hook Parameters: ​identifier​
  • Callback Parameters: ​expression​
new MyClass();

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

expression

SyncBailHook

该钩子会在解析表达式时被触发

  • Hook Parameters: ​identifier​
  • Callback Parameters: ​expression​
const a = this;

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

expressionConditionalOperator

SyncBailHook

在解析条件表达式(例如 condition ? a : b)时调用

  • Callback Parameters: ​expression​

program

SyncBailHook

获取代码片段的抽象语法树(AST)的访问权限

  • Parameters: ​ast​ ​comments​