Skip to content

webpack 原理和二次开发

仲灏约 1 分钟

webpack 原理和二次开发

这部分是面试的加分项,大家不要深究细节。即便面试被问到,实际工作中应用的概率也非常小。 webpack 本身就是一个工具,只是用来打包构建。而且发展多年已经成熟完善,日常的开发场景都能满足。


webpack 构建流程

几个核心概念

  • Entry:入口,Webpack 执行构建的第一步将从 Entry 开始,可抽象成输入。
  • Module:模块,在 Webpack 里一切皆模块,一个模块对应着一个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。
  • Chunk:代码块,一个 Chunk 由多个模块组合而成,用于代码合并与分割。
  • Loader:模块转换器,用于把模块原内容按照需求转换成新内容。
  • Plugin:扩展插件,在 Webpack 构建流程中的特定时机会广播出对应的事件,插件可以监听这些事件的发生,在特定时机做对应的事情。

Webpack 的构建流程可以分为以下三大阶段:

  • 初始化:启动构建,读取与合并配置参数,加载 Plugin,实例化 Compiler。
  • 编译:从 Entry 发出,针对每个 Module 串行调用对应的 Loader 去翻译文件内容,再找到该 Module 依赖的 Module,递归地进行编译处理。
  • 输出:对编译后的 Module 组合成 Chunk,把 Chunk 转换成文件,输出到文件系统。

开发 loader

less-loader 为例,回顾一下使用规则

js
{
    test: /\.less$/,
    // 注意顺序
    loader: ['style-loader', 'css-loader', 'less-loader']
}

所以,loader 的作用:

  • 一个代码转换器,将 less 代码转换为 css 代码
  • 再例如 vue-template-compiler
  • 再例如 babel 编译 jsx

所以一个 loader 的基本开发模式:

js
const less = require('node-less')
module.exports = function(source) {
  // source 即 less 代码,需要返回 css 代码
  return less(source)
}

以上是 loader 的基本开发方式,实际开发中可能还会有更多要求

  • 支持 options ,如 url-loader 的使用
  • 支持异步 loader
  • 缓存策略
js
// options
const loaderUtils = require('loader-utils')
module.exports = function(source) {
  // 获取 loader 的 options
  const options = loaderUtils.getOptions(this)
  return source // 示例,直接返回 source 了
}
js
// 异步 loader
module.exports = function(source) {
    // 使用异步 loader
    const callback = this.async()
    // 执行异步函数,如读取文件
    someAsyncFn(source, function(err, result, sourceMaps, ast) {
        // 通过 callback 返回异步执行后的结果
        callback(err, result, sourceMaps, ast)
    })
}
js
// 缓存
module.exports = function(source) {
  // 关闭该 Loader 的缓存功能(webpack 默认开启缓存)
  this.cacheable(false)
  return source
}

上次更新:

讨论区

欢迎留下想法与补充