返回

构建 Module 的工作流程(下)

前端

一、继续分析 runLoaders 之后的逻辑

在上一篇文章中,我们分析了 Webpack 4 中 runLoaders 函数的上半部分,包括如何创建 loader 上下文对象、如何执行 loader 以及如何处理 loader 的错误。在本文中,我们将继续分析 runLoaders 函数的下半部分,包括如何处理 loader 的回调、如何创建源代码以及如何处理源代码。

  1. 处理 loader 的回调

在 loader 执行完毕后,会触发一个回调函数。该回调函数有两个参数:result 和 resourceBuffer。result 是 loader 执行后的结果,它可以是一个字符串、一个对象或一个 Buffer。resourceBuffer 是 loader 执行前的源代码。

callback(err, result, resourceBuffer);
  • 如果 result 是一个字符串,则它将被视为源代码。
  • 如果 result 是一个对象,则它必须包含一个 source 属性,该属性的值将被视为源代码。
  • 如果 result 是一个 Buffer,则它将被转换为字符串,然后被视为源代码。
  1. 创建源代码

在处理完 loader 的回调之后,Webpack 会调用 createSource 函数来创建源代码。createSource 函数接收两个参数:result 和 resourceBuffer。result 是 loader 执行后的结果,resourceBuffer 是 loader 执行前的源代码。

function createSource(result, resourceBuffer) {
  if (typeof result === 'string') {
    return new RawSource(result);
  } else if (Buffer.isBuffer(result)) {
    return new RawSource(result.toString());
  } else if (typeof result === 'object' && result.source) {
    return result.source;
  } else {
    throw new Error('Invalid loader result');
  }
}

createSource 函数首先会判断 result 的类型。如果 result 是一个字符串,则它将被直接返回。如果 result 是一个 Buffer,则它将被转换为字符串,然后返回。如果 result 是一个对象,并且该对象包含一个 source 属性,则 source 属性的值将被返回。否则,createSource 函数将抛出一个错误。

  1. 处理源代码

在创建完源代码之后,Webpack 会调用 handleSource 函数来处理源代码。handleSource 函数接收两个参数:source 和 resourceBuffer。source 是创建的源代码,resourceBuffer 是 loader 执行前的源代码。

function handleSource(source, resourceBuffer) {
  if (compilation.options.module.needAdditionalPass) {
    return handleSourceAsync(source, resourceBuffer);
  } else {
    return handleSourceSync(source, resourceBuffer);
  }
}

handleSource 函数首先会判断 compilation.options.module.needAdditionalPass 的值。如果该值为 true,则它会调用 handleSourceAsync 函数来处理源代码。否则,它会调用 handleSourceSync 函数来处理源代码。

handleSourceAsync 函数会创建一个异步任务,然后将源代码和 resourceBuffer 传递给该异步任务。异步任务会调用 loader 来处理源代码。在 loader 处理完源代码之后,异步任务会将处理后的源代码返回给 handleSourceAsync 函数。handleSourceAsync 函数会将处理后的源代码返回给 handleSource 函数。

handleSourceSync 函数会直接调用 loader 来处理源代码。在 loader 处理完源代码之后,handleSourceSync 函数会将处理后的源代码返回给 handleSource 函数。

  1. 处理依赖项

在处理完源代码之后,Webpack 会调用 processDependencies 函数来处理依赖项。processDependencies 函数接收一个参数:module。module 是当前正在处理的模块。

function processDependencies(module) {
  const dependencies = module.dependencies;
  for (let i = 0; i < dependencies.length; i++) {
    const dependency = dependencies[i];
    dependency.updateHash(module.hash);
    if (dependency.module) {
      processDependencies(dependency.module);
    }
  }
}

processDependencies 函数首先会获取当前模块的依赖项。然后,它会遍历