当前位置: 首页 > Web前端 > HTML

webpack5源码详解-攻略

时间:2023-03-28 14:49:31 HTML

阅读源码攻略webpack源码非常庞大,而且配置非常丰富,阅读起来非常吃力。有很多重要的功能模块、概念、独立于webpack的包等,在阅读源码之前最好单独整理一下,做个简单的介绍,更有利于后续阅读。Compilerwebpack在运行时,会传入配置信息,并返回一个实例化的Compiler对象。它在运行环境上是独一无二的,所有的主要流程都由它来控制,比如开始编译,从入口点开始处理模块,根据配置把不同的模块封装成一个组,最后生成文件等等。当然,它只是一个操作流程,流程中的一切都委托给其他模块处理。Compilation可以调用很多处理模块的方法,并保存相应的构建信息,如modules、assets、moduleGraph、chunkGraph等,每次资源重构都会生成一个新的Compilation。Module在webpack中,一切都是模块,js文件,图片,视频等。普通模块会生成NormalModule对象,可以调用方法解析模块,可以调用parser解析成AST(抽象语法树)等。NormalModule对象包含了Loader处理的代码,解析导入了哪个模块,解析的模块路径,引入的其他模块的依赖。并且在构建模块时,会生成一个moduleGraph记录模块之间的引用信息,导出信息可以保存下来分析导出是否被使用过。Chunk构建完成后,如果不做相关配置,所有模块都会打包在一个Chunk中,但你也可以自己配置,使用最好的方式将代码切块,优化网页的加载速度。Loaderwebpack可以处理js,webpack5也增加了很多处理其他资源的能力。但是,还有很多文件是webpack本身无法处理的,需要引入其他Loader将其转化为js,才能被webpack操作。如果想写一个Loader来处理相关资源,可以看文档。Plugin插件可以帮助webpack扩展功能,包括很多内置的功能也是通过插件引入的,比如热模块替换、external、splitChunk等,都是从Tapable扩展出来的,优点是可以扩展webpack的功能并与webpack解耦。如果想写Plugin扩展功能,可以看这里ParserParser是用来解析资源的,最常用的解析器是JavascriptParser。它使用acorn将js解析成AST(抽象语法树),并遍历所有的声明或表达式,找出相关模块的导入导出信息,添加到依赖中。它还可以收集导出和导入条件,为后续的tree-shaking做准备。也可以解析评论,实现webpack魔术评论功能。除了JavascriptParser,还有webassemblyParser,会调用@webassemblyjs/ast进行解析。还有cssParser、jsonParser等独立库。除了webpack的核心代码之外,它还将很多功能集成到一个库中。这些库不仅用于webpack,还用于vanillaJs。Tapable是贯穿webpack全文的库。基础和重要的功能模块都有它的身影,功能模块和插件之间的通信都需要依赖它。在webpack中叫做hooks,其实就是一个高级的EventEmitter。我也写了一篇详细的文章来介绍一下。如果要写插件,最好知道webpack的主模块中有哪些hook:loader路径信息,也可以支持很多配置。比如我们最常用的配置是resolve.alias,通过别名导入资源更方便,还有resolve.extensions增加文件扩展名等,webpack的resolve选项就是用来配置这个库的。loader-runnerloader-runner用于执行webpackloader。webpack-sourceswebpack-sources可以生成源码的sourceMap、hash等运行环境webpackv5.70.0webpack.config.jsconstpath=require("path");const{CleanWebpackPlugin}=require("clean-webpack-plugin");module.exports={mode:"development",devtool:"source-map",entry:"./index.js",output:{path:path.join(__dirname,"./dist"),文件名:"[fullhash].[name].bundle.js"},优化:{usedExports:true},插件:[newCleanWebpackPlugin()]};index.jsimport{c_var}from"./module_c"import(/*webpackExports:["a"]*/"./module_a").then(({a})=>{console.log(a)})varlog_var=c_var;console.log(log_var)module_c.jsconstc_var="module_c";constb_var="unused";export{c_var,b_var};module_a.jsexportconsta="moudle_a";exportconstb="unused";export{a,b};条目是./index。js的执行目录上下文为c:\Users\Administrator\Desktop\webpack进程。webpack的流程可以分为四大块。运行初始化、编译准备、处理选项、规则、注册插件、实例化编译器需要的其他对象等。make通过入口文件开始构建模块,构建模块会分为几个步骤,比如解析路径,通过loader转换模块,用paser收集依赖,递归处理所有外部依赖。sealseal是一个属于Compilation的hook,不像run、make、emit都属于Compiler,单独拿出来是因为很多东西都是这个阶段做的,也是make之后执行的。在seal阶段,不再接收模块,会根据ChunkGroup封装成一个或多个chunk,然后做一些代码优化,生成文件Hash名等。在emit输出文件阶段,webpack会根据不同的模板生成代码,有些代码会被替换,比如import和export会被替换成__webpack_require__,__webpack_exports__等,webpack的很多代码都是根据有没有配置来运行的,因为只是为了理解打包过程方便调试,所以后续的大部分代码示例都会去掉一些无用的代码,错误处理,实现缓存的代码等。而且运行模式是“开发”,“生产”下的很多配置都会默认为true,会压缩代码,不利于理解。