在compiler中找到的parser实例用于解析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(/* ... */);
});
});
与编译器一样,tapAsync 和 tapPromise 也可能可用,具体取决于钩子的类型。
parser暴露了以下生命周期钩子,可以通过以下方式访问它们
SyncBailHook
当评估一个包含自由变量的typeof表达式时触发
identifierexpressionparser.hooks.evaluateTypeof
.for('myIdentifier')
.tap('MyPlugin', (expression) => {
/* ... */
return expressionResult;
});
这将触发evaluateTypeof钩子
const a = typeof myIdentifier;
这不会触发
const myIdentifier = 0;
const b = typeof myIdentifier;
SyncBailHook
在评估表达式时调用。
expressionTypeexpression例如
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'SyncBailHook
在评估作为自由变量的标识符时调用。
identifierexpressionSyncBailHook
在评估作为已定义变量的标识符时调用。
identifierexpressionSyncBailHook
在评估成功评估的表达式的成员函数调用时调用。
identifierexpression param此表达式将触发钩子
index.js
const a = expression.myFunc();
MyPlugin.js
parser.hooks.evaluateCallExpressionMember
.for('myFunc')
.tap('MyPlugin', (expression, param) => {
/* ... */
return expressionResult;
});
SyncBailHook
一个通用钩子,用于代码片段中每个解析的语句。
statementparser.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'SyncBailHook
在解析if语句时调用。与statement钩子相同,但仅当statement.type == 'IfStatement'时触发。
statementSyncBailHook
在解析带有label的语句时调用。这些语句的statement.type === 'LabeledStatement'。
labelNamestatementSyncBailHook
为代码片段中的每个import语句调用。source参数包含导入文件的名称。
statement source以下import语句将触发钩子一次
index.js
import _ from 'lodash';
MyPlugin.js
parser.hooks.import.tap('MyPlugin', (statement, source) => {
// source == 'lodash'
});
SyncBailHook
为每个import语句的每个说明符调用。
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'
*/
}
);
SyncBailHook
为代码片段中的每个export语句调用。
statementSyncBailHook
为每个export-import语句(例如:export * from 'otherModule';)调用。
statement sourceSyncBailHook
为每个导出声明的export语句调用。
statement declaration这些导出将触发此钩子
export const myVar = 'hello'; // also var, let
export function FunctionName() {}
export class ClassName {}
SyncBailHook
为每个导出表达式的export语句(例如export default expression;)调用。
statement declarationSyncBailHook
为每个export语句的每个说明符调用。
statement identifierName exportName indexSyncBailHook
为每个export-import语句的每个说明符调用。
statement source identifierName exportName indexSyncBailHook
在解析变量声明时调用。
declarationSyncBailHook
在解析使用let定义的变量声明时调用
declarationSyncBailHook
在解析使用const定义的变量声明时调用
declarationSyncBailHook
在解析使用var定义的变量声明时调用
declarationSyncBailHook
在重命名标识符之前触发,以确定是否允许重命名。这通常与rename钩子一起使用。
identifierexpressionvar a = b;
parser.hooks.canRename.for('b').tap('MyPlugin', (expression) => {
// returning true allows renaming
return true;
});
SyncBailHook
在重命名时触发,以获取新的标识符。此钩子仅当canRename返回true时才会被调用。
identifierexpressionvar a = b;
parser.hooks.rename.for('b').tap('MyPlugin', (expression) => {});
SyncBailHook
在解析AssignmentExpression之前,先解析被赋值的表达式时调用。
identifierexpressiona += b;
parser.hooks.assigned.for('a').tap('MyPlugin', (expression) => {
// this is called before parsing b
});
SyncBailHook
在解析AssignmentExpression之前,先解析赋值表达式时调用。
identifierexpressiona += b;
parser.hooks.assigned.for('a').tap('MyPlugin', (expression) => {
// this is called before parsing a
});
SyncBailHook
在解析标识符的typeof时触发
identifierexpressionSyncBailHook
在解析函数调用时调用。
identifierexpressioneval(/* something */);
parser.hooks.call.for('eval').tap('MyPlugin', (expression) => {});
SyncBailHook
在解析对对象成员函数的调用时触发。
objectIdentifierexpression, propertiesmyObj.anyFunc();
parser.hooks.callMemberChain
.for('myObj')
.tap('MyPlugin', (expression, properties) => {});
SyncBailHook
在解析new表达式时调用。
identifierexpressionnew MyClass();
parser.hooks.new.for('MyClass').tap('MyPlugin', (expression) => {});
SyncBailHook
在解析表达式时调用。
identifierexpressionconst a = this;
parser.hooks.expression.for('this').tap('MyPlugin', (expression) => {});
SyncBailHook
在解析ConditionalExpression(例如condition ? a : b)时调用
expressionSyncBailHook
访问代码片段的抽象语法树(AST)
ast comments