# max-mini-webpack **Repository Path**: max-lu/max-mini-webpack ## Basic Information - **Project Name**: max-mini-webpack - **Description**: 简约版webpack - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-12-15 - **Last Updated**: 2021-12-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: webpack ## README # webpack **模块分析项目打包**角度 ## 前置知识 + Tapable **Tapable**包本质上是为我们更方面创建自定义事件和触发自定义事件的库,类似于`Nodejs`中的`EventEmitter Api`。 `Webpack`中的插件机制就是基于Tapable实现与打包流程解耦,插件的所有形式都是基于`Tapable`实现。 + Webpack Node Api 基于学习目的我们会着重于`Webpack Node Api`流程去讲解,实际上我们在前端日常使用的`npm run build`命令也是通过环境变量调用`bin`脚本去调用`Node Api`去执行编译打包。 + Babel `Webpack`内部的`AST`分析同样依赖于`Babel`进行处理 ## 流程梳理 + 初始化参数 这一步会从我们配置的`webpack.config.js`中读取到对应的配置参数和`shell`命令中传入的参数进行合并得到最终打包配置参数。 + 编译 这一步我们会通过调用`webpack()`方法返回一个`compiler`方法,创建我们的`compiler`对象,并且注册各个`Webpack Plugin`。找到配置入口中的`entry`代码,调用`compiler.run()`方法进行编译。 + 模块编译 从入口模块进行分析,调用匹配文件的`loaders`对文件进行处理。同时分析模块依赖的模块,递归进行模块编译工作 + 完成编译 在递归完成后,每个引用模块通过`loaders`处理完成同时得到模块之间的相互依赖关系 + 输出文件 整理模块依赖关系,同时将处理后的文件输出到`ouput`的磁盘目录中 ## 模块编译(详解) + 根据入口文件路径分析入口文件,对于入口文件进行匹配对应的loader进行处理入口文件 + 将loader处理完成的入口文件使用 webpack 进行编译 + 分析入口文件依赖,重复上边两个步骤编译对应依赖 + 如果嵌套文件存在依赖文件,嘀咕调用依赖模块进行编译 + 递归编译完成后,组装一个个包含多个模块的chunk +++ ### `buildModule`模块编译方法 + 接受两个参数进行模块编译:第一个为模块所属的入口**文件名称**。第二个为需要编译的**模块路径** + 代码编译的前提:通过fs模块工具入口文件路径**读取文件源代码** + 读取文件内容后,调用所有匹配的**loader对模块进行处理**得到返回后的结果 + 得到loader处理后的结果,通过**babel分析**loader处理后的代码,进行代码编译(主要是require语句,修改源代码中require语句的路径) + 如果该入口文件没有依赖任何模块(require语句),那么返回编译后的模块对象 + 如果该入口文件存在依赖的模块。**递归buildModule**方法进行模块编译 +++ ### exportFile输出代码到文件 - 首先获取配置参数的输出配置,迭代我们的`this.chunks`,将`output.filename`中的`[name]`替换称为对应的入口文件名称。同时根据`chunks`的内容为`this.assets`中添加需要打包生成的文件名和文件内容。 - 将文件写入磁盘前调用`plugin`的`emit`钩子函数。 - 判断`output.path`文件夹是否存在,如果不存在,则通过`fs`新建这个文件夹。 - 将本次打包生成的所有文件名(`this.assets`的`key`值组成的数组)存放进入`files`中去。 - 循环`this.assets`,将文件依次写入对应的磁盘中去。 - 所有打包流程结束,触发`webpack`插件的`done`钩子。 - 同时为`NodeJs Webpack APi`呼应,调用`run`方法中外部传入的`callback`传入两个参数。 总的来说,`this.assets`做的事情也比较简单,就是通过分析`chunks`得到`assets`然后输出对应的代码到磁盘中。 +++ ## 插件(Plugin) 是一个**类** webpack插件本质上就是通过 **发布订阅** 的模式,通过compiler上监听事件。然后在打包编译过程中触发监听的事件从而添加一定的逻辑影响打包结果 ``` 任何一个webpack插件都是一个类,每个插件都必须存在一个apply方法 这个apply方法接收一个compiler对象 所以:编写webpack plugin时本质上就是操作compiler对象从而影响打包结果 ``` ## Loader loader本质就是一个**函数**,接受我们的源代码作为入参,同时返回处理后的结果 ## 参考 [希望没有过期](https://mp.weixin.qq.com/s/soLeN5xwFTCSUXoZxJAssw?)