阅读(1920) (0)

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