# webpack-analysis **Repository Path**: luoyisen/webpack-analysis ## Basic Information - **Project Name**: webpack-analysis - **Description**: webpack学习学习,手写一下webpack的构建流程,撸一下webpack官网文档 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-02-21 - **Last Updated**: 2023-03-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README [Loader Interface | webpack 中文文档 | webpack 中文文档 | webpack 中文网 (webpackjs.com)](https://www.webpackjs.com/api/loaders/#pitching-loader) ## API ### 简介 Webpack 提供了多种接口来自定义编译过程。 接口间存在一些重叠功能,例如配置选项可能通过 CLI 标志启用, 而其他仅存在于单个接口。 ### CLI 命令行界面(CLI), 用于配置构建并与之交互。它在早期原型制作和性能分析的情况下特别有用。 大多数情况下, CLI 只是用于通过配置文件和一些标志(例如 `--env`)来启动进程。 ### 模块 使用 webpack 处理模块时, 最重要的是理解不同的模块语法 - 特别是受支持的[方法](https://www.webpackjs.com/api/module-methods)和[变量](https://www.webpackjs.com/api/module-variables)。 ### Node 尽管大多数用户可以借助 CLI 和配置文件控制编译, 通过 Node 接口可以实现更细粒度的控制。 这包括传递多个配置、 以程序的方式运行、查阅并收集统计信息。 ### Loaders Loaders 用于对模块的源代码进行转换。 它们被编写成一类将源代码作为参数传入, 并将编译转换后的新版本代码传出的函数体。 ### 插件 插件接口允许用户直接介入编译过程。 插件可以在不同时期运行的生命周期挂钩上注册回调函数。 在单个编译流程中,当每个钩子都被执行后,插件将拥有 当前编译流程的完整访问权限。 ## Node 接口 导入的 `webpack` 函数会将 [配置对象](https://www.webpackjs.com/configuration/) 传给 webpack,如果同时传入回调函数会在 webpack compiler 运行时被执行,如果你不向 `webpack` 传入可执行的回调函数, 它会返回一个 webpack `Compiler` 实例。 ### Compiler 实例(Compiler Instance) 通常情况下,仅会创建一个主要 `Compiler` 实例, 虽然可以创建一些子 compiler 来代理到特定任务。 `Compiler` 基本上只是执行最低限度的功能,以维持生命周期运行的功能。 它将所有的加载、打包和写入工作, 都委托到注册过的插件上。 ### 执行(Run) 使用 `run` 方法启动所有编译工作。 完成之后,执行传入的 `callback` 函数。 最终记录下来的概括信息(stats)和错误(errors),都应在这个 callback 函数中获取。 ### 监听(Watching) 调用 `watch` 方法会触发 webpack 执行,但之后会监听变更(很像 CLI 命令: `webpack --watch`), 一旦 webpack 检测到文件变更,就会重新执行编译。 该方法返回一个 `Watching` 实例。 #### 关闭 `Watching` (Close `Watching`) `watch` 方法返回一个 `Watching` 实例,该实例会暴露一个 `.close(callback)` 方法。 调用该方法将会结束监听 #### Invalidate `Watching` 使用 `watching.invalidate`,你可以手动使当前编译循环(compiling round)无效, 而不会停止监听进程(process) ### Stats 对象(Stats Object) `stats` 对象会被作为 [`webpack()`](https://www.webpackjs.com/api/node/#webpack) 回调函数的第二个参数传递, 可以通过它获取到代码编译过程中的有用信息, 包括: * 错误和警告(如果有的话) * 计时信息 * module 和 chunk 信息 [webpack CLI](https://www.webpackjs.com/api/cli) 正是基于这些信息在控制台 展示友好的格式输出。 `stats` 对象暴露了以下方法: #### stats.hasErrors() 可以用来检查编译期是否有错误, 返回值为 `true` 或 `false`。 #### stats.hasWarnings() 可以用来检查编译期是否有警告, 返回值为 `true` 或 `false`。 #### stats.toJson(options) 以 JSON 对象形式返回编译信息。 `options` 可以是一个字符串(预设值)或是颗粒化控制的对象 ### MultiCompiler `MultiCompiler` 模块可以让 webpack 同时执行多个配置。 如果传给 webpack 的 Node.js API 的 `options` 参数, 该参数由是由多个配置对象构成的数组,webpack 会相应地创建多个 compiler 实例, 并且在所有 compiler 执行完毕后调用 `callback` 方法。 ### 错误处理(Error Handling) 完备的错误处理中需要考虑以下三种类型的错误: * 致命的 wepback 错误(配置出错等) * 编译错误(缺失的 module,语法错误等) * 编译警告 ### 自定义文件系统(Custom File Systems) 默认情况下,webpack 使用普通文件系统来读取文件并将文件写入磁盘。 但是,还可以使用不同类型的文件系统(内存(memory), webDAV 等)来更改输入或输出行为。 为了实现这一点, 可以改变 `inputFileSystem` 或 `outputFileSystem`。 例如,可以使用 [`memfs`](https://github.com/streamich/memfs) 替换默认的 `outputFileSystem`, 以将文件写入到内存中, 而不是写入到磁盘,被 [webpack-dev-server](https://github.com/webpack/webpack-dev-server) 及众多其他包依赖的 [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) 就是通过这种方式, 将你的文件神秘地隐藏起来,但却仍然可以用它们为浏览器提供服务! ## Logger 接口 使用 Logger 输出消息是一种向用户展示信息的有效方式。 Webpack Logger 可以用在 [loader](https://www.webpackjs.com/loaders/) 和 [plugin](https://www.webpackjs.com/api/plugins/#logging)。生成的 Logger 将作为 [统计信息](https://www.webpackjs.com/api/stats/) 的一部分进行输出,并且用户可以在 [webpack 配置文件](https://www.webpackjs.com/configuration/) 中对 Logger 进行配置。 在 Webpack 中使用自定义 Logger API 的优点: * 可以 [配置](https://www.webpackjs.com/configuration/stats/#statslogging) 日志的展示级别 * 日志内容可作为 `stats.json` 的一部分输出 * 统计预设会影响日志的输出 * 使用 plugin 可以影响日志的捕获与展示级别 * 当使用多个 plugin 和 loader 时,提供更加通用的日志记录解决方案 * 基于 Webpack 开发的 CLI、UI 工具等可能会选择不同的方式来展示日志 * Webpack 核心可以触发日志输出,例如:timing data 通过引入 Webpack Logger API,我们希望统一 Webpack plugins 和 loaders 生成日志的方式,并提供更好的方法来检查构建问题。 集成的 Logging 解决方案可以帮助 plugins 和 loader 的开发人员提升他们的开发经验。同时为非 CLI 形式的 Webpack 解决方案构建铺平了道路,例如 dashboard 或其他 UI。 *warning:**避免在日志中输出无效信息!** 请记住,多个 plugin 和 loader 经常一起使用。loader 通常处理多个文件,并且每个文件都会调用,所以尽可能选择较低的日志级别以保证 log 的信息量。* ## Loader API * 同步loader,loader里只有同步操作,使用return或者this.callback返回编译后的内容 * 异步loader,loader里有异步操作,使用this.async告知编译器对象获取this.callback * raw loader,exports.raw设置为true,使loader接收raw buffer数据 * pitch loader,在loader执行前执行的函数 ### loader的执行顺序 loader按执行顺序分可分为前置(pre)、普通(normal)、行内(inline)、后置(post) loader。 #### 有两个执行阶段 * Pitching阶段:post > inline > normal > pre * Normal阶段:pre > normal > inline > post 正常情况是 Pitching阶段 > Normal阶段 。 ##### 熔断:其中loader的pitch方法如果返回结果,webpack会直接跳出Pitching阶段而进入Normal阶段,并且该loader与后续被跳过pitching阶段的loader的normal方法也不会被调用。 ##### 行内loader的前缀: * !,跳过normal loader * -!,跳过pre loader 与normal loader * !!,跳过pre loader、normal loader 与 post loader pitching loader:https://www.webpackjs.com/api/loaders/#pitching-loader 前置、后置loader:https://www.webpackjs.com/configuration/module#ruleenforce ## Plugin API **插件** 是 webpack 的 [支柱](https://github.com/webpack/tapable) 功能。Webpack 自身也是构建于你在 webpack 配置中用到的 **相同的插件系统** 之上! 插件目的在于解决 [loader](https://www.webpackjs.com/concepts/loaders) 无法实现的 **其他事** 。Webpack 提供很多开箱即用的 [插件](https://www.webpackjs.com/plugins/)。 webpack **插件**是一个具有 [`apply`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) 方法的 JavaScript 对象。`apply` 方法会被 webpack compiler 调用,并且在 **整个** 编译生命周期都可以访问 compiler 对象。 webpack compiler使用到了tapable类实现发布订阅模式,webpack的构建过程会发布许多的事件,plugin就是通过webpack compiler来订阅这些事件进行操作。 ### tapable类 hooks * basic hook,这个hook会调用所有tap订阅 * waterfall,这个hook会调用所有的tap订阅,但上一个订阅的返回值会传到下一个订阅 * bail,这个hook允许提早退出hooks的调用,如果其中一个订阅返回值不为undefined,剩余的订阅将不会执行 * loop,这个hook允许重新执行订阅,如果其中一个订阅返回值不为undefined,他将会从第一个订阅重新执行 * sync,同步hoook * AsyncSeries,异步串行hook * AsyncParallel,异步并行hook