Webpack插件和loader开发配置

偏向技术
/ 0 评论 / 162 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2021年04月01日,已超过2013天没有更新,若内容或图片失效,请留言反馈。

Compilation Object

Compilation 对象有很多可用的方法和钩子。在此页面,我们将会列举出这些可用的方法和属性。

compilation 对象方法

  1. getStats

    function

    返回当前编译的状态对象。

  2. addModule

    function (module, cacheGroup)

    向当前编译添加一个模块。

    参数:

    • module - 要添加的模块
    • cacheGroup - 模块的 cacheGroup
  3. getModule

    function (module)

    通过编译的标识符获取其模块。

    参数:

    • module - 要获取的模块。标识符是通过编译使用 module.identifier() 方法从模块中提取的。
  4. findModule

    function (module)

    尝试通过其标识符搜索模块。

    参数:

    • module - 要搜索的模块。标识符是通过编译使用 module.identifier() 方法从模块中提取的。
  5. waitForBuildingFinished

    function (module, callback)

    在构建给定模块时运行给定的 callback 函数。

    参数:

    • module - 有问题的模块。
    • callback - 要调用的函数。
  6. buildModule

    function (module, optional, origin, dependencies)

    构建给定的模块。

    参数:

    • module - 要构建的模块。
    • optional - 可选标志。
    • origin - 请求此模块构建的原始模块。
    • dependencies - 要构建模块的可选依赖。
  7. processModuleDependencies

    function (module, callback)

    处理给定模块依赖。

    参数:

    • module - 要被处理依赖的模块。
    • callback - 模块依赖处理完成时回调的函数。
  8. addModuleDependencies

    function (module, dependencies, bail, cacheGroup, recursive, callback)

    向模块添加依赖。处理依赖之后被 processModuleDependencies 自动调用。

    参数:

    • module - 要添加依赖的模块。
    • dependencies - 要遍历添加到模块的一组已排序依赖。
    • bail - 发生错误时是否中断进程并抛出 error。
    • cacheGroup - 模块的 cacheGroup。
    • recursive - 是否要递归遍历。
    • callback - 添加模块依赖之后回调的函数。
  9. addEntry

    function (context, entry, name, callback)

    为编译添加入口。

    参数:

    • context - 入口的上下文路径。
    • entry - 入口依赖。
    • name - 入口名称。
    • callback - 添加入口完成之后回调的函数。
  10. prefetch

    function (context, dependency, callback)

    根据给定的依赖创建一个模块。

    参数:

    • context - 上下文路径。
    • dependency - 被用来创建模块的依赖。
    • callback - 向上一级发送模块的模块回调。
  11. rebuildModule

    function (module, thisCallback)

    触发模块的重建。

    参数:

    • module - 要被重建的模块。
    • thisCallback - 模块重建完成之后调用的函数。
  12. finish

    function (callback)

    完成编译并调用给定的回调。

    参数:

    • callback - 编译完成之后调用的函数。
  13. seal

    function (callback)

    封闭编译。

    参数:

    • callback - 封闭编译时回调的函数。
  14. unseal

    function

    解除封闭编译。

    参数:

    • callback - 解除封闭编译时回调的函数。
  15. reportDependencyErrorsAndWarnings

    function (module, blocks)

    将给定模块的错误和警告添加到编译的错误和警告中。

    参数:

    • module - 要被报告错误与警告的模块。
    • blocks - 一组要报告的依赖块。
  16. addChunkInGroup

    function (groupOptions, module, loc, request)

    将模块添加到现有 chunk 组或创建一个新的组。返回一个 chunkGroup。

    参数:

    • groupOptions - chunk 组的选项。
    • module - 引用 chunk 组的模块。
    • loc - 引用 chunk 组的位置(模块内部)。
    • request - 引用 chunk 组的请求。
  17. addChunk

    function (name)

    向 compilation.chunks 创建或添加一个新的 chunk。返回这个 chunk.

    参数:

    • name - chunk 的名称。
  18. assignDepth

    function (module)

    为给定的模块及其依赖块递归分配 depth 。

    参数:

    • module - 要被分配 depth 的模块。
  19. getDependencyReference

    function (module, dependency)

    返回给定模块对依赖的引用。

    参数:

    • module - 有问题的模块。
    • dependency - 要引用的依赖。
  20. processDependenciesBlocksForChunkGroups

    function (inputChunkGroups)

    通过 Module 图创建 Chunk 图。该过程分为两个阶段完成。阶段一:遍历模块图,在 chunkDependencies 中创建一个基础 chunk 图。阶段二:通过基本 chunk 图遍历所有可能的方法并且跟踪可用模块。遍历过程中 processDependenciesBlocksForChunkGroups 将 chunk 相互连接,并将 Blocks 与 Chunks 连接. 当一个 chunk 的所有模块都已经可用且未连接不需要的 chunk 时,它将停止遍历。

    参数:

    • inputChunkGroups - 被处理的 chunk 组。
  21. removeReasonsOfDependencyBlock

    function (module, block)

    移除模块与依赖块之间的关系。

    参数:

    • module - 要移除的模块关系。
    • block - 依赖块。
  22. patchChunksAfterReasonRemoval

    function (module, chunk)

    删除依赖性原因后,修补模块和 chunk 的关系。被 removeReasonsOfDependencyBlock 自动调用。

    参数:

    • module - 要修复关系的模块。
    • chunk - 要修复关系的 chunk。
  23. removeChunkFromDependencies

    function (block, chunk)

    在除去依赖性原因后,从依赖块模块和 chunk 中移除给定的 chunk。会被 removeReasonsOfDependencyBlock 自动调用。

    参数:

    • block - Chunk 的块连接。
    • chunk - 从依赖中删除的块。
  24. sortItemsWithModuleIds

    function

  25. sortItemsWithChunkIds

    function

  26. summarizeDependencies

    function

  27. createHash

    function

  28. createModuleAssets

    function

  29. createChunkAssets

    function

  30. getPath

    function (filename, data)

    返回插值路径。

    参数:

    • filename - 用于通过哈希获取资源路径。
    • data - 数据对象。
  31. getPathWithInfo

    function (filename, data)

    返回插值路径和资源信息。

    参数:

    • filename - 用于通过哈希获取资源路径。
    • data - 数据对象。
  32. createChildCompiler

    function (name, outputOptions, plugins)

    允许在 webpack 中运行另一个 webpack 实例。但是,子编译器会应用不同的设置和配置。他会从父编译器(或者顶级编译器)中复制所有的钩子(hook)和插件(plugin),并且创建一个子 Compiler 实例。 返回值为创建好的 Compiler 实例。

    参数:

    • name - 子 Compiler 的名称。
    • outputOptions - 输出选项。
    • plugins - 将被提供的 webpack 插件。
  33. checkConstraints

    function

  34. emitAsset

    function (file, source, assetInfo = {})

    webpack 4.40.0 后可用。

    参数:

    • file - 资源名称。
    • source - 资源来源。
    • assetInfo - 附加资源信息。
  35. updateAsset

    function (file, newSourceOrFunction, assetInfoUpdateOrFunction)

    webpack 4.40.0 后可用。

    参数:

    • file - 资源名称。
    • newSourceOrFunction - 新资源来源或将旧资源转换为新资源的函数。
    • assetInfoUpdateOrFunction - 新资源信息或将旧资源转换为新资源的函数。
  36. deleteAsset

    function (file)

    参数:

    • file —— 资源的文件名
  37. getAssets

    function

    webpack 4.40.0 后可用。

    返回当前编译下所有资源的数组。

  38. getAsset

    function (name)

    webpack 4.40.0 后可用。

    参数:

    • name - 要返回的资源名称。

compiler 钩子

Compiler 模块是 webpack 的主要引擎,它通过 CLI 传递的所有选项, 或者 Node API,创建出一个 compilation 实例。 它扩展(extend)自 Tapable 类,用来注册和调用插件。 大多数面向用户的插件会首先在 Compiler 上注册。

此模块会暴露在 webpack.Compiler, 可以直接通过这种方式使用。 关于更多信息,请查看 这个示例。

在为 webpack 开发插件时,你可能需要知道每个钩子函数是在哪里调用的。想要了解这些内容,请在 webpack 源码中搜索 hooks.<hook name>.call。

监听(watching)

Compiler 支持可以监控文件系统的 监听(watching) 机制,并且在文件修改时重新编译。 当处于监听模式(watch mode)时, compiler 会触发诸如 watchRun, watchClose 和 invalid 等额外的事件。 通常在 开发环境 中使用, 也常常会在 webpack-dev-server 这些工具的底层调用, 由此开发人员无须每次都使用手动方式重新编译。 还可以通过 CLI 进入监听模式。

钩子

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

js
compiler.hooks.someHook.tap('MyPlugin', (params) => {
  /* ... */
});
123

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

关于钩子类型的描述,请查看 Tapable 文档.

  1. entryOption

    SyncBailHook

    在 webpack 选项中的 entry 被处理过之后调用。

    js
    compiler.hooks.entryOption.tap('MyPlugin', (context, entry) => {
      /* ... */
    });
    123

    参数:context, entry

  2. afterPlugins

    SyncHook

    在初始化内部插件集合完成设置之后调用。

    • 回调参数:compiler
  3. afterResolvers

    SyncHook

    resolver 设置完成之后触发。

    • 回调参数:compiler
  4. environment

    SyncHook

    在初始化配置文件中的插件之后立即调用,在 compiler environment 准备时调用。

  5. afterEnvironment

    SyncHook

    在 environment 钩子之后立即调用,在 compiler environment 完成设置时调用。

  6. beforeRun

    AsyncSeriesHook

    在开始执行一次构建之前调用,compiler.run 方法开始执行后立刻进行调用。

    • 回调参数:compiler
  7. additionalPass

    AsyncSeriesHook

    This hook allows you to do a one more additional pass of the build.

  8. run

    AsyncSeriesHook

    在开始读取 records 之前调用。

    • 回调参数:compiler
  9. watchRun

    AsyncSeriesHook

    在监听模式下,一个新的 compilation 触发之后,但在 compilation 实际开始之前执行。

    • 回调参数:compiler
  10. normalModuleFactory

    SyncHook

    NormalModuleFactory 创建之后调用。

    • 回调参数:normalModuleFactory
  11. contextModuleFactory

    SyncHook

    ContextModuleFactory 创建之后调用。

    • 回调参数:contextModuleFactory
  12. initialize

    SyncHook

    在初始化 compiler 对象时调用。

  13. beforeCompile

    AsyncSeriesHook

    在创建 compilation parameter 之后执行。

    • 回调参数:compilationParams

    初始化 compilationParams 变量的示例如下:

    js
     compilationParams = {
       normalModuleFactory,
       contextModuleFactory,
     };
    1234

    此钩子可用于添加/修改 compilation parameter:

    js
     compiler.hooks.beforeCompile.tapAsync('MyPlugin', (params, callback) => {
       params['MyPlugin - data'] = 'important stuff my plugin will use later';
       callback();
     });
    1234
  14. compile

    SyncHook

    beforeCompile 之后立即调用,但在一个新的 compilation 创建之前。

    • 回调参数:compilationParams
  15. thisCompilation

    SyncHook

    初始化 compilation 时调用,在触发 compilation 事件之前调用。

    • 回调参数:compilation, compilationParams
  16. compilation

    SyncHook

    compilation 创建之后执行。

    • 回调参数:compilation, compilationParams
  17. make

    AsyncParallelHook

    compilation 结束之前执行。

    • 回调参数:compilation
  18. afterCompile

    AsyncSeriesHook

    compilation 结束和封印之后执行。

    • 回调参数:compilation
  19. shouldEmit

    SyncBailHook

    在输出 asset 之前调用。返回一个布尔值,告知是否输出。

    • 回调参数:compilation
    js
     compiler.hooks.shouldEmit.tap('MyPlugin', (compilation) => {
       // 返回 true 以输出 output 结果,否则返回 false
       return true;
     });
    1234
  20. emit

    AsyncSeriesHook

    输出 asset 到 output 目录之前执行。

    • 回调参数:compilation
  21. afterEmit

    AsyncSeriesHook

    输出 asset 到 output 目录之后执行。

    • 回调参数:compilation
  22. assetEmitted

    AsyncSeriesHook

    在 asset 被输出时执行。此钩子可以访问被输出的 asset 的相关信息,例如它的输出路径和字节内容。

    • 回调参数:file, info

    例如,可以通过 info.content 访问 asset 的内容 buffer:

    js
     compiler.hooks.assetEmitted.tap(
       'MyPlugin',
       (file, { content, source, outputPath, compilation, targetPath }) => {
         console.log(content); // <Buffer 66 6f 6f 62 61 72>
       }
     );
    123456
  23. done

    AsyncSeriesHook

    在 compilation 完成时执行。

    • 回调参数:stats
  24. failed

    SyncHook

    在 compilation 失败时调用。

    • 回调参数:error
  25. invalid

    SyncHook

    在一个观察中的 compilation 无效时执行。

    • 回调参数:fileName, changeTime
  26. watchClose

    SyncHook

    在一个观察中的 compilation 停止时执行。

  27. infrastructureLog

    SyncBailHook

    在配置中启用 infrastructureLogging 选项 后,允许使用 infrastructure log(基础日志)。

    • 回调参数:name, type, args
  28. log

    SyncBailHook

    启用后允许记录到 stats 对象,请参阅 stats.logging, stats.loggingDebug 和 stats.loggingTrace 选项。

    • 回调参数:origin, logEntry

compilation 钩子

Compilation 模块会被 Compiler 用来创建新的 compilation 对象(或新的 build 对象)。 compilation 实例能够访问所有的模块和它们的依赖(大部分是循环依赖)。 它会对应用程序的依赖图中所有模块, 进行字面上的编译(literal compilation)。 在编译阶段,模块会被加载(load)、封存(seal)、优化(optimize)、 分块(chunk)、哈希(hash)和重新创建(restore)。

Compilation 类扩展(extend)自 Tapable,并提供了以下生命周期钩子。 可以按照 compiler 钩子的相同方式来调用 tap:

js
compilation.hooks.someHook.tap(/* ... */);
1

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

  1. buildModule

    SyncHook

    在模块构建开始之前触发,可以用来修改模块。

    • 回调参数:module
    js
    compilation.hooks.buildModule.tap('SourceMapDevToolModuleOptionsPlugin',
      module => {
        module.useSourceMap = true;
      }
    );
    12345
  2. rebuildModule

    SyncHook

    在重新构建一个模块之前触发。

    • 回调参数:module
  3. failedModule

    SyncHook

    模块构建失败时执行。

    • 回调参数:module error
  4. succeedModule

    SyncHook

    模块构建成功时执行。

    • 回调参数:module
  5. finishModules

    AsyncSeriesHook

    所有模块都完成构建并且没有错误时执行。

    • 回调参数:modules
  6. finishRebuildingModule

    SyncHook

    一个模块完成重新构建时执行,在都成功或有错误的情况下。

    • 回调参数:module
  7. seal

    SyncHook

    compilation 对象停止接收新的模块时触发。

  8. unseal

    SyncHook

    compilation 对象开始接收新模块时触发。

  9. optimizeDependencies

    SyncBailHook

    依赖优化开始时触发。

    • 回调参数:modules
  10. afterOptimizeDependencies

    SyncHook

    依赖优化之后触发。

    • 回调参数:modules
  11. optimize

    SyncHook

    优化阶段开始时触发。

  12. optimizeModules

    SyncBailHook

    在模块优化阶段开始时调用。插件可以 tap 此钩子对模块进行优化。

    • 回调参数:modules
  13. afterOptimizeModules

    SyncHook

    在模块优化完成之后调用。

    • 回调参数:modules
  14. optimizeChunks

    SyncBailHook

    在 chunk 优化阶段开始时调用。插件可以 tap 此钩子对 chunk 执行优化。

    • 回调参数:chunks
  15. afterOptimizeChunks

    SyncHook

    chunk 优化完成之后触发。

    • 回调参数:chunks
  16. optimizeTree

    AsyncSeriesHook

    在优化依赖树之前调用。插件可以 tap 此钩子执行依赖树优化。

    • 回调参数:chunks modules
  17. afterOptimizeTree

    SyncHook

    在依赖树优化成功完成之后调用。

    • 回调参数:chunks modules
  18. optimizeChunkModules

    SyncBailHook

    在树优化之后,chunk 模块优化开始时调用。插件可以 tap 此钩子来执行 chunk 模块的优化。

    • 回调参数:chunks modules
  19. afterOptimizeChunkModules

    SyncHook

    在 chunk 模块优化成功完成之后调用。

    • 回调参数:chunks modules
  20. shouldRecord

    SyncBailHook

    调用来决定是否存储 record。返回任何内容 !== false 将阻止执行所有其他 "record" 钩子(record, recordModules, recordChunks 和 recordHash)。

  21. reviveModules

    SyncHook

    从 record 中恢复模块信息。

    • 回调参数:modules records
  22. beforeModuleIds

    SyncHook

    在为每个模块分配 id 之前执行。

    • 回调参数:modules
  23. moduleIds

    SyncHook

    调用来每个模块分配一个 id。

    • 回调参数:modules
  24. optimizeModuleIds

    SyncHook

    在模块 id 优化开始时调用。

    • 回调参数:modules
  25. afterOptimizeModuleIds

    SyncHook

    在模块 id 优化完成时调用。

    • 回调参数:modules
  26. reviveChunks

    SyncHook

    从 record 中恢复 chunk 信息。

    • 回调参数:chunks records
  27. beforeChunkIds

    SyncHook

    在为每个 chunk 分配 id 之前执行。

    • 回调参数:chunks
  28. chunkIds

    SyncHook

    调用时,会为每个 chunk 分配一个 id。

    • 回调函数的参数为:chunks
  29. optimizeChunkIds

    SyncHook

    在 chunk id 优化阶段开始时调用。

    • 回调参数:chunks
  30. afterOptimizeChunkIds

    SyncHook

    chunk id 优化结束之后触发。

    • 回调参数:chunks
  31. recordModules

    SyncHook

    将模块信息存储到 record 中。shouldRecord 返回 truthy 值时触发。

    • 回调参数:modules records
  32. recordChunks

    SyncHook

    将 chunk 存储到 record 中。shouldRecord 返回 truthy 值时触发。

    • 回调参数:chunks records
  33. beforeHash

    SyncHook

    在 compilation 添加哈希(hash)之前。

  34. afterHash

    SyncHook

    在 compilation 添加哈希(hash)之后。

  35. recordHash

    SyncHook

    将有关 record 的信息存储到 records 中。仅在 shouldRecord 返回 truthy 值时触发。

    • 回调参数:records
  36. record

    SyncHook

    将 compilation 相关信息存储到 record 中。仅在 shouldRecord 返回 truthy 值时触发。

    • 回调参数:compilation records
  37. beforeModuleAssets

    SyncHook

    在创建模块 asset 之前执行。

  38. additionalChunkAssets

    SyncHook

    additionalChunkAssets 已弃用(可使用 Compilation.hook.processAssets 来代替,并且可使用 Compilation.PROCESSASSETS_STAGE* 作为其选项参数。)

    为这些 chunk 创建其他 asset。

    • 回调参数:chunks
  39. shouldGenerateChunkAssets

    SyncBailHook

    调用以确定是否生成 chunk asset。返回任何 !== false 将允许生成 chunk asset。

  40. beforeChunkAssets

    SyncHook

    在创建 chunk asset 之前。

  41. additionalAssets

    AsyncSeriesHook

    为 compilation 创建额外 asset。 这个钩子可以用来下载图像,例如:

    js
     compilation.hooks.additionalAssets.tapAsync('MyPlugin', callback => {
       download('https://img.shields.io/npm/v/webpack.svg', function(resp) {
         if(resp.status === 200) {
           compilation.assets['webpack-version.svg'] = toAsset(resp);
           callback();
         } else {
           callback(new Error('[webpack-example-plugin] Unable to download the image'));
         }
       });
     });
    12345678910
  42. optimizeChunkAssets

    AsyncSeriesHook

    optimizeChunkAssets 已弃用。(可使用 Compilation.hook.processAssets 来代替,并且可使用 Compilation.PROCESSASSETS_STAGE* 作为其选项参数。

    优化所有 chunk asset。asset 存储在 compilation.assets 中。 每个 Chunk 都具有一个 files 属性,其指向由一个 chunk 创建的所有文件。 任何额外 chunk asset 都存储在 compilation.additionalChunkAssets 中。

    • 回调参数:chunks

    Here's an example that simply adds a banner to each chunk.

    js
     compilation.hooks
       .optimizeChunkAssets
       .tapAsync('MyPlugin', (chunks, callback) => {
         chunks.forEach(chunk => {
           chunk.files.forEach(file => {
             compilation.assets[file] = new ConcatSource(
               '\/**Sweet Banner**\/',
               '\n',
               compilation.assets[file]
             );
           });
         });
    
         callback();
       });
    123456789101112131415
  43. afterOptimizeChunkAssets

    SyncHook

    afterOptimizeChunkAssets 已弃用。(可使用 Compilation.hook.processAssets 来代替,并且可使用 Compilation.PROCESSASSETS_STAGE*作为其选项参数。

    chunk asset 已经被优化。

    • 回调参数:chunks

    这里是一个来自 @boopathi 的示例插件,详细地输出每个 chunk 里有什么。

    js
     compilation.hooks.afterOptimizeChunkAssets.tap('MyPlugin', chunks => {
       chunks.forEach(chunk => {
         console.log({
           id: chunk.id,
           name: chunk.name,
           includes: chunk.getModules().map(module => module.request)
         });
       });
     });
    123456789
  44. optimizeAssets

    AsyncSeriesHook

    优化存储在 compilation.assets 中的所有 asset。

    • 回调参数:assets
  45. afterOptimizeAssets

    SyncHook

    asset 已经优化。

    • 回调参数:assets
  46. processAssets

    AsyncSeriesHook

    Asset processing.

    • Callback Parameters: assets

    Here's an example:

    js
     compilation.hooks.processAssets.tap(
       {
         name: 'MyPlugin',
         stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONS, // see below for more stages
       },
       (assets) => {
         // code here
       }
     );
    123456789

    In addition to name and stage, you can pass a additionalAssets 5.8.0+ option which accepts either a value of true or a function with assets as parameter:

    1. true - Run callback against assets added later by plugins.

      js
      compilation.hooks.processAssets.tap(
        {
          name: 'MyPlugin',
          stage: Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING,
          additionalAssets: true
        },
        (assets) => {
          // this callback will run against assets added later by plugins.
        }
      );
      12345678910
    2. (assets) => {} - Run this specified callback against assets added later by plugins.

      js
      compilation.hooks.processAssets.tap(
        {
          name: 'MyPlugin',
          stage: Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING,
          additionalAssets: (assets) => {
            // this callback will run against assets added later by plugins.
          }
        },
        (assets) => {
          // code
        }
      );
      123456789101112

    Here's a list of stages we can use:

    • PROCESS_ASSETS_STAGE_ADDITIONAL - Add additional assets to the compilation.
    • PROCESS_ASSETS_STAGE_PRE_PROCESS - Basic preprocessing of the assets.
    • PROCESS_ASSETS_STAGE_DERIVED - Derive new assets from the existing assets.
    • PROCESS_ASSETS_STAGE_ADDITIONS - Add additional sections to the existing assets e.g. banner or initialization code.
    • PROCESS_ASSETS_STAGE_OPTIMIZE - Optimize existing assets in a general way.
    • PROCESS_ASSETS_STAGE_OPTIMIZE_COUNT - Optimize the count of existing assets, e.g. by merging them.
    • PROCESS_ASSETS_STAGE_OPTIMIZE_COMPATIBILITY - Optimize the compatibility of existing assets, e.g. add polyfills or vendor prefixes.
    • PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE - Optimize the size of existing assets, e.g. by minimizing or omitting whitespace.
    • PROCESS_ASSETS_STAGE_DEV_TOOLING - Add development tooling to the assets, e.g. by extracting a source map.
    • PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE 5.8.0+ - Optimize the numbers of existing assets, e.g. by inlining assets into other assets.
    • PROCESS_ASSETS_STAGE_SUMMARIZE - Summarize the list of existing assets.
    • PROCESS_ASSETS_STAGE_OPTIMIZE_HASH - Optimize the hashes of the assets, e.g. by generating real hashes of the asset content.
    • PROCESS_ASSETS_STAGE_OPTIMIZE_TRANSFER - Optimize the transfer of existing assets, e.g. by preparing a compressed (gzip) file as separate asset.
    • PROCESS_ASSETS_STAGE_ANALYSE - Analyze the existing assets.
    • PROCESS_ASSETS_STAGE_REPORT - Creating assets for the reporting purposes.
  47. afterProcessAssets

    SyncHook

    Called after the processAssets hook had finished without error.

  48. needAdditionalSeal

    SyncBailHook

    调用来决定 compilation 是否需要解除 seal 以引入其他文件。

  49. afterSeal

    AsyncSeriesHook

    在 needAdditionalSeal 之后立即执行。

  50. chunkHash

    SyncHook

    触发来为每个 chunk 生成 hash。

    • 回调参数:chunk chunkHash
  51. moduleAsset

    SyncHook

    一个模块中的一个 asset 被添加到 compilation 时调用。

    • 回调参数:module filename
  52. chunkAsset

    SyncHook

    一个 chunk 中的一个 asset 被添加到 compilation 时调用。

    • 回调参数:chunk filename
  53. assetPath

    SyncWaterfallHook

    调用以决定 asset 的路径。

    • 回调参数:path options
  54. needAdditionalPass

    SyncBailHook

    调用以决定 asset 在输出后是否需要进一步处理。

  55. childCompiler

    SyncHook

    子 compiler 设置之后执行。

    • 回调参数:childCompiler compilerName compilerIndex
  56. normalModuleLoader

    从 webpack v5 开始,normalModuleLoader 钩子已经删除。现在要访问loader 请改用 NormalModule.getCompilationHooks(compilation).loader。

JavascriptParser Hooks

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

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

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

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

钩子

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

  1. evaluateTypeof

    SyncBailHook

    Triggered when evaluating an expression consisting in a typeof of a free variable

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

    这会触发 evaluateTypeof 钩子的调用:

    js
    const a = typeof myIdentifier;
    1

    This won't trigger:

    js
    const myIdentifier = 0;
    const b = typeof myIdentifier;
    12
  2. evaluate

    SyncBailHook

    Called when evaluating an expression.

    • Hook parameters: expressionType
    • Callback parameters: expression

    For example:

    index.js

    js
    const a = new String();
    1

    MyPlugin.js

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

    Where the expressions types are:

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

    SyncBailHook

    Called when evaluating an identifier that is a free variable.

    • Hook Parameters: identifier
    • Callback Parameters: expression
  4. evaluateDefinedIdentifier

    SyncBailHook

    Called when evaluating an identifier that is a defined variable.

    • Hook Parameters: identifier
    • Callback Parameters: expression
  5. evaluateCallExpressionMember

    SyncBailHook

    Called when evaluating a call to a member function of a successfully evaluated expression.

    • Hook Parameters: identifier
    • Callback Parameters: expression param

    This expression will trigger the hook:

    index.js

    js
    const a = expression.myFunc();
    1

    MyPlugin.js

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

    SyncBailHook

    General purpose hook that is called for every parsed statement in a code fragment.

    • Callback Parameters: statement
    js
    parser.hooks.statement.tap('MyPlugin', statement => { /* ... */ });
    1

    Where the statement.type could be:

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

    SyncBailHook

    Called when parsing an if statement. Same as the statement hook, but triggered only when statement.type == 'IfStatement'.

    • Callback Parameters: statement
  8. label

    SyncBailHook

    Called when parsing statements with a label. Those statements have statement.type === 'LabeledStatement'.

    • Hook Parameters: labelName
    • Callback Parameters: statement
  9. import

    SyncBailHook

    Called for every import statement in a code fragment. The source parameter contains the name of the imported file.

    • Callback Parameters: statement source

    The following import statement will trigger the hook once:

    index.js

    js
    import _ from 'lodash';
    1

    MyPlugin.js

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

    SyncBailHook

    Called for every specifier of every import statement.

    • Callback Parameters: statement source exportName identifierName

    The following import statement will trigger the hook twice:

    index.js

    js
     import _, { has } from 'lodash';
    1

    MyPlugin.js

    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'
       */
     });
    123456789101112
  11. export

    SyncBailHook

    Called for every export statement in a code fragment.

    • Callback Parameters: statement
  12. exportImport

    SyncBailHook

    Called for every export-import statement eg: export * from 'otherModule';.

    • Callback Parameters: statement source
  13. exportDeclaration

    SyncBailHook

    Called for every export statement exporting a declaration.

    • Callback Parameters: statement declaration

    Those exports will trigger this hook:

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

    SyncBailHook

    Called for every export statement exporting an expression e.g.export default expression;.

    • Callback Parameters: statement declaration
  15. exportSpecifier

    SyncBailHook

    Called for every specifier of every export statement.

    • Callback Parameters: statement identifierName exportName index
  16. exportImportSpecifier

    SyncBailHook

    Called for every specifier of every export-import statement.

    • Callback Parameters: statement source identifierName exportName index
  17. varDeclaration

    SyncBailHook

    Called when parsing a variable declaration.

    • Callback Parameters: declaration
  18. varDeclarationLet

    SyncBailHook

    Called when parsing a variable declaration defined using let

    • Callback Parameters: declaration
  19. varDeclarationConst

    SyncBailHook

    Called when parsing a variable declaration defined using const

    • Callback Parameters: declaration
  20. varDeclarationVar

    SyncBailHook

    Called when parsing a variable declaration defined using var

    • Callback Parameters: declaration
  21. canRename

    SyncBailHook

    Triggered before renaming an identifier to determine if the renaming is allowed. This is usually used together with the rename hook.

    • Hook Parameters: identifier
    • Callback Parameters: expression
    js
     var a = b;
    
     parser.hooks.canRename.for('b').tap('MyPlugin', expression => {
       // returning true allows renaming
       return true;
     });
    123456
  22. rename

    SyncBailHook

    Triggered when renaming to get the new identifier. This hook will be called only if canRename returns true.

    • Hook Parameters: identifier
    • Callback Parameters: expression
    js
     var a = b;
    
     parser.hooks.rename.for('b').tap('MyPlugin', expression => {});
    123
  23. assigned

    SyncBailHook

    Called when parsing an AssignmentExpression before parsing the assigned expression.

    • Hook Parameters: identifier
    • Callback Parameters: expression
    js
     a += b;
    
     parser.hooks.assigned.for('a').tap('MyPlugin', expression => {
       // this is called before parsing b
     });
    12345
  24. assign

    SyncBailHook

    Called when parsing an AssignmentExpression before parsing the assign expression.

    • Hook Parameters: identifier
    • Callback Parameters: expression
    js
     a += b;
    
     parser.hooks.assigned.for('a').tap('MyPlugin', expression => {
       // this is called before parsing a
     });
    12345
  25. typeof

    SyncBailHook

    Triggered when parsing the typeof of an identifier

    • Hook Parameters: identifier
    • Callback Parameters: expression
  26. call

    SyncBailHook

    Called when parsing a function call.

    • Hook Parameters: identifier
    • Callback Parameters: expression
    js
     eval(/* something */);
    
     parser.hooks.call.for('eval').tap('MyPlugin', expression => {});
    123
  27. callAnyMember

    SyncBailHook

    Triggered when parsing a call to a member function of an object.

    • Hook Parameters: objectIdentifier
    • Callback Parameters: expression
    js
     myObj.anyFunc();
    
     parser.hooks.callAnyMember.for('myObj').tap('MyPlugin', expression => {});
    123
  28. new

    SyncBailHook

    Invoked when parsing a new expression.

    • Hook Parameters: identifier
    • Callback Parameters: expression
    js
     new MyClass();
    
     parser.hooks.new.for('MyClass').tap('MyPlugin', expression => {});
    123
  29. expression

    SyncBailHook

    Called when parsing an expression.

    • Hook Parameters: identifier
    • Callback Parameters: expression
    js
     const a = this;
    
     parser.hooks.expression.for('this').tap('MyPlugin', expression => {});
    123
  30. expressionConditionalOperator

    SyncBailHook

    Called when parsing a ConditionalExpression e.g. condition ? a : b

    • Callback Parameters: expression
  31. program

    SyncBailHook

    Get access to the abstract syntax tree (AST) of a code fragment

    • Parameters: ast comments

Plugin API

插件是 webpack 生态的关键部分, 它为社区用户提供了一种强有力的方式来直接触及 webpack 的编译过程(compilation process)。 插件能够 hook 到每一个编译(compilation)中发出的关键事件中。 在编译的每个阶段中,插件都拥有对 compiler 对象的完全访问能力, 并且在合适的时机,还可以访问当前的 compilation 对象。

Tapable

这个小型库是 webpack 的一个核心工具,但也可用于其他地方, 以提供类似的插件接口。 在 webpack 中的许多对象都扩展自 Tapable 类。 它对外暴露了 tap,tapAsync 和 tapPromise 等方法, 插件可以使用这些方法向 webpack 中注入自定义构建的步骤,这些步骤将在构建过程中触发。

请查阅文档了解更多知识。 理解上面的的三种 tap 方法, 以及提供这些方法的钩子(hooks)对于编写插件来说是至关重要的。 那些扩展自 Tapable 的对象(例如:compiler), 以及其提供的钩子(hooks)和每个钩子的类型(例如:同步钩子(SyncHook))值得关注。

插件类型

根据使用不同的钩子(hooks)和 tap 方法, 插件可以以多种不同的方式运行。 这个工作方式与 Tapable 提供的钩子(hooks)密切相关。 compiler hooks 分别记录了 Tapable 内在的钩子, 并指出哪些 tap 方法可用。

所以,依赖于使用的 tap 方法的不同, 插件可能会以不同的方式运行。 例如:当你钩入到 编译(compile) 阶段时,只有同步的 tap 方法可以使用。

js
compiler.hooks.compile.tap('MyPlugin', params => {
  console.log('以同步方式触及 compile 钩子。');
});
123

然而,对于可以使用 AsyncHook 的 run 阶段, 则需使用 tapAsync 或 tapPromise(以及 tap)方法。

js
compiler.hooks.run.tapAsync('MyPlugin', (source, target, routesList, callback) => {
  console.log('以异步方式触及 run 钩子。');
  callback();
});

compiler.hooks.run.tapPromise('MyPlugin', (source, target, routesList) => {
  return new Promise(resolve => setTimeout(resolve, 1000)).then(() => {
    console.log('以具有延迟的异步方式触及 run 钩子。');
  });
});

compiler.hooks.run.tapPromise('MyPlugin', async (source, target, routesList) => {
  await new Promise(resolve => setTimeout(resolve, 1000));
  console.log('以具有延迟的异步方式触及 run 钩子。');
});
123456789101112131415

这些需求(story)的含义在于, 我们可以有多种方式 hook 到 compiler 中,可以让各种插件都以合适的方式去运行。

自定义钩子

为了便于其他插件的编译过程中可以 tap 到,则需要创建一个新的 hook, 我们只需要简单的从 tapable 中 require 所需的 hook 类,并创建:

js
const SyncHook = require('tapable').SyncHook;

if (compiler.hooks.myCustomHook) throw new Error('已存在该钩子');
compiler.hooks.myCustomHook = new SyncHook(['a', 'b', 'c']);

// 在你想要触发钩子的位置/时机下调用……
compiler.hooks.myCustomHook.call(a, b, c);
1234567

再次声明, 查看 tapable 文档 来了解更多不同的钩子类(hook class),以及它们是如何工作的。

进度报告

插件能够通过 ProgressPlugin 这个在默认情况下将信息打印到标准错误输出(stderr)的插件来进行进度报告。如果想要使用这个功能,只需要在使用 webpack CLI 的时候传入 --progress 参数。

如果想要自定义打印输出,只需要传递不同的参数到 ProgressPlugin 的 reportProgress 方法。

如果想要报告进度,插件必须在 tap 到 hook 的时候使用 context: true 选项。

js
compiler.hooks.emit.tapAsync({
  name: 'MyPlugin',
  context: true
}, (context, compiler, callback) => {
  const reportProgress = context && context.reportProgress;
  if (reportProgress) reportProgress(0.95, 'Starting work');
  setTimeout(() => {
    if (reportProgress) reportProgress(0.95, 'Done work');
    callback();
  }, 1000);
});
1234567891011

reportProgress 方法在被调用的时候会传入以下的参数:

js
reportProgress(percentage, ...args);
1
  • percentage:此参数未使用。作为代替,ProgressPlugin 插件会基于当前的钩子(hook)计算进度。
  • ...args:任意数量的字符串,这些字符串会传递给 ProgressPlugin 插件并报告给用户。

注意:只有 compiler 和 compilation 钩子的子集才支持 reportProgress 方法。请查看 ProgressPlugin 了解更多信息

日志

日志的 API 在 webpack 4.37 版本后提供支持。当 logging 在 统计配置(stats configuration)中可用和(或)当 infrastructure logging 可用的时候,插件会通过各自的记录格式(stats,infrastructure)打印信息。

  • 插件可以使用 compilation.getLogger('PluginName') 来做记录。这种形式的记录保存在统计数据(Stats)中并做相应的格式化。它能够被用户过滤和导出。
  • 插件也可以使用 compilation.getInfrastructureLogger('PluginName') 来做记录。使用 infrastructure 的形式并不会被保存在统计数据(Stats)中,因此也不会被格式化。它通常直接将记录载入到 console/dashboard/GUI 中。它能够被用户过滤。
  • 插件也可以使用特殊的降级逻辑 compilation.getLogger ? compilation.getLogger('PluginName') : console 来检测是否支持记录,以此来在不支持 compilation.getLogger 方法的旧版本 webpack 中提供降级方法。

解析器(Resolvers)

解析器是使用 enhanced-resolve 库创建的。Resolver 类 拓展了 tapable 类,并使用 tapable 来提供了一些钩子。 enhanced-resolve 可以直接用于创建新的解析器, 但是,任何 compiler 实例 都有一些解析器实例,可以 被 tap 进去。

在继续阅读之前,请确保你已经读过 enhanced-resolve 和 tapable 文档。

类型

在 compiler 类中,提供了三种类型的内置解析器:

  • normal: 通过绝对或相对路径解析模块。
  • context: 在给定的上下文中解析模块。
  • loader: 解析 webpack loader。

根据需要,任一个被使用在 compiler 中的内置解析器, 可以通过插件进行定制:

js
compiler.resolverFactory.hooks.resolver.for('[type]').tap('name', resolver => {
  // you can tap into resolver.hooks now
  resolver.hooks.result.tap('MyPlugin', result => {
    return result;
  });
});
123456

其中,[type] 是上述三个解析器之一。

请参阅 enhanced-resolve documentation 以获得钩子的完整列表以及它们的介绍。

配置选项

上述解析器也可以 利用 resolve or resolveLoader 选项,通过配置文件进行定制。这些选项允许 用户可以通过多种选项来更改解析行为,包括 通过解析 plugins。

解析器插件,例如:DirectoryNamedPlugin,可以直接引入 在 resolve.plugins,而不是直接在 plugins configuration option 中使用。

请注意,resolve 配置会影响 normal 解析器和 context 解析器,而“ resolveLoader 用于修改 loader 解析器。

0

评论 (0)

取消