| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> JavaScript知识库 -> webpack解析初探 -> 正文阅读 |
|
[JavaScript知识库]webpack解析初探 |
最近花了一点时间探究webpack5的源码,通过网上的一些文章的辅助去更好的理解这个项目。接下来分析一个常规的解析过程。 首先是是使用vscode的Node调试,通过vscode的run?and?debug添加调试配置,默认生成的launch.json文件如下{ ????"version":?"0.2.0", ????"configurations":?[ ????????{ ????????????"type":?"pwa-node", ????????????"request":?"launch", ????????????"name":?"Launch?Program", ????????????"skipFiles":?[ ????????????????"<node_internals>/**" ????????????], ????????????"program":?"${workspaceFolder}\\mytest\\index.js" ????????} ????] } 配置program调试入口,然后点击三角形按钮就可以调试代码。 ? ? 如图在新建了一个mytest的文件夹下创建一个index.js作为调试的入口,掉用lib/index.js。引入webpack在lib/webpack.js中导出函数,调用这个函数一步步往下执行。 在开始之前我们先来了解一下Hooks类使用的是tapable,?它包含几个方法SyncHook, ????SyncBailHook,? ????AsyncParallelHook, ????AsyncSeriesHook 通过tap注册事件和回调,并通过call,callAsync,promise.then来触发。当然还可以注册拦截器来监听hook执行的各个阶段。 Tapable是webpack的精髓,通过hook注册和触发事件,贯穿整个构件解析的生命周期,后面的解析我们会讲到,compiler以及compiler.compilation都注册了很多操作的Hooks. 接下来我们正是进入源码,lib/webpack.js中导出的函数,主要是create函数创建并返回compiler实例和watch标记以及watchOptions配置。 当我们的调用的函数存在回调是会判断是否是watch,是的话执行compiler.watch,否则执行compiler.run。 const?{?compiler,?watch,?watchOptions?}?=?create(); ????????????????if?(watch)?{ ????????????????????compiler.watch(watchOptions,?callback); ????????????????}?else?{ ????????????????????compiler.run((err,?stats)?=>?{ ????????????????????????compiler.close(err2?=>?{ ????????????????????????????callback(err?||?err2,?stats); ????????????????????????}); ????????????????????}); ????????????????} ????????????????return?compiler; 可以构件单个compiler调用的是createCompiler,后者多个createMultiCompiler,下面我们一单个为例 const?createCompiler?=?rawOptions?=>?{ ????const?options?=?getNormalizedWebpackOptions(rawOptions); ????applyWebpackOptionsBaseDefaults(options); ????const?compiler?=?new?Compiler(options.context,?options); ????new?NodeEnvironmentPlugin({ ????????infrastructureLogging:?options.infrastructureLogging ????}).apply(compiler); ????if?(Array.isArray(options.plugins))?{ ????????for?(const?plugin?of?options.plugins)?{ ????????????if?(typeof?plugin?===?"function")?{ ????????????????plugin.call(compiler,?compiler); ????????????}?else?{ ????????????????plugin.apply(compiler); ????????????} ????????} ????} ????applyWebpackOptionsDefaults(options); ????compiler.hooks.environment.call(); ????compiler.hooks.afterEnvironment.call(); ????new?WebpackOptionsApply().process(options,?compiler); ????compiler.hooks.initialize.call(); ????return?compiler; }; 首先是获取用户的配置加上默认的配置,生成最新的配置。然后创建compiler实例, NodeEnvironmentPlugin插件是用来扩展node,加文件缓存、文件读取和写入、文件监听。这里文件监听使用的是Watchpack库。 执行用户配置的插件,在添加webpac默认配置。 接下来所有重要的逻辑都是在WebpackOptionsApply这里面处理的,通过配置去执行对应的插件。 compiler.hooks.make.tapAsync("EntryPlugin",?(compilation,?callback)?=>?{ ????????????compilation.addEntry(context,?dep,?options,?err?=>?{ ????????????????callback(err); ????????????}); ????????}); 主要来看入口文件的处理,?EntryOptionPlugin插件中EntryPlugin通过调用compilation.addEntry从入口文件开始处理。 此外如果入口是一个函数,则调用DynamicEntryPlugin也会添加入口文件。 在网上看到别人分析的源码,我觉得这张图结构很清晰,可以说明的生命周期的各个阶段所做的事: ? addEntry方法中调用addModuleTree去处理相关的模块依赖,调用dependencyFactories 处理模块的依赖dependency.constructor。然后handleModuleCreation内部处理,最后调用factorizeModule解析模块。用factorizeQueue将模块解析压入模块解析队列中执行。 首先调用工程的factory.create函数,调用的是compilation.dependencyFactories.set( ????????????????????EntryDependency, ????????????????????normalModuleFactory ????????????????); 放入的normalModuleFactory。 大致步骤addModule添加模块,然后_handleModuleBuildAndDependencies构建模块buildModule和处理模块依赖processModuleDependencies。通过_processModuleDependencies方法中handleModuleCreation循环构建。 在构建过程中需要处理一些loader,在NormalModule中调用_doBuild中的runLoaders去处理,最终返回资源和webpackAST信息。 最后调用compilation.seal将模块转换成chunk代码块,最后通过emitAssets输出合并后的代码块输出文件。 ? |
|
JavaScript知识库 最新文章 |
ES6的相关知识点 |
react 函数式组件 & react其他一些总结 |
Vue基础超详细 |
前端JS也可以连点成线(Vue中运用 AntVG6) |
Vue事件处理的基本使用 |
Vue后台项目的记录 (一) |
前后端分离vue跨域,devServer配置proxy代理 |
TypeScript |
初识vuex |
vue项目安装包指令收集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 9:44:58- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |