Skip to content

Webpack 问与答

webpack 的作用是什么?

  • 模块打包。将不同模块的文件打包整合在一起,并且保证它们之间的引用正确,执行有序。

  • 编译兼容。通过 webpack 的 Loader 机制,不仅仅可以对代码做 polyfill,还可以编译转换诸如.less, .vue, .jsx 这类在浏览器无法识别的格式文件。

  • 能力扩展。 通过 webpack 的 Plugin 机制,可以进一步实现诸如按需加载,代码压缩等一系列功能。

模块打包的运行原理?

答案参考 Webpack 核心原理

sourceMap 是什么?

  • 定义:sourceMap 是一项将编译、打包、压缩后的代码映射回源代码的技术。
  • 作用:sourceMap 可以帮助我们快速定位到源代码的位置,提高开发效率。
  • 使用:development 开发模式下,每个__webpack_modules__ 文件模块的代码最末端,都会加上 //# sourceURL=webpack://file-path?,从而实现对 sourceMap 的支持。

编写 loader 的思路?

  • 意义:Webpack 内部默认只能够处理 JS 模块代码;需要 Loader 机制,先对其进行必要的转换,才能继续执行打包任务。
  • 当 Webpack 在转换该文件类型的时候,会按顺序链式调用每一个 loader,前一个 loader 返回的内容会作为下一个 loader 的入参。
  • loader 函数中的 this 上下文由 webpack 提供,可以通过 this 对象提供的相关属性,获取当前loader需要的各种信息数据。事实上,this 指向了一个叫 loaderContext 的 loader-runner 特有对象。
module.exports = function(source) {
    const content = doSomeThing2JsString(source);

    // 如果 loader 配置了 options 对象,那么this.query将指向 options
    const options = this.query;

    // 可以用作解析其他模块路径的上下文
    console.log('this.context');

    /*
     * this.callback 参数:
     * error:Error | null,当 loader 出错时向外抛出一个 error
     * content:String | Buffer,经过 loader 编译后需要导出的内容
     * sourceMap:为方便调试生成的编译后内容的 source map
     * ast:本次编译生成的 AST 静态语法树,之后执行的 loader 可以直接使用这个 AST,进而省去重复生成 AST 的过程
     */
    this.callback(null, content);
    // or return content;
}

编写 plugin 的思路?

  • webpack基于发布订阅模式,在运行的生命周期中会广播出许多事件,插件通过监听这些事件,就可以在特定的阶段执行自己的插件任务,从而实现自己想要的功能。

  • 其中 compiler 暴露了和 Webpack 整个生命周期相关的钩子(compiler-hooks),而 compilation 则暴露了与模块和依赖有关的粒度更小的事件钩子(Compilation Hooks)。

  • Plugin 的开发需要遵循一些规范和原则:

    • 插件必须是一个函数或者是一个包含 apply 方法的对象,这样才能访问 compiler 实例;
    • 传给每个插件的 compiler 和 compilation 对象都是同一个引用,若在一个插件中修改了它们身上的属性,会影响后面的插件;
    • 异步的事件需要在插件处理完任务时调用回调函数通知 Webpack 进入下一个流程,不然会卡住;
class MyPlugin {
  apply (compiler) {
    // 找到合适的事件钩子,实现自己的插件功能
    compiler.hooks.emit.tap('MyPlugin', compilation => {
      // compilation: 当前打包构建流程的上下文
      console.log(compilation);
      // do something...
    })
  }
}