首页 > 编程语言 >webpack2源码架构设计与构建流程

webpack2源码架构设计与构建流程

时间:2024-07-16 15:57:48浏览次数:10  
标签:架构设计 webpack2 name 源码 new entry options 打包 compiler

入口初始化

入口文件lib/webpack.js

function webpack(options, callback) {
	let compiler;
	if(Array.isArray(options)) {
		compiler = new MultiCompiler(options.map(options => webpack(options)));
	} else if(typeof options === "object") {
                //创建默认options
		new WebpackOptionsDefaulter().process(options);

                //创建compiler对象
		compiler = new Compiler();
		compiler.context = options.context;
		compiler.options = options;

		/* 遍历用户的插件并注册 */
		if(options.plugins && Array.isArray(options.plugins)) {
			compiler.apply.apply(compiler, options.plugins);
		}
		
                 //注册内置插件、注册resolverFactory相关的钩子
		compiler.options = new WebpackOptionsApply().process(options, compiler);
	}
	if(callback) {
                //开始构建
		compiler.run(callback);
	}
	return compiler;
}
//WebpackOptionsApply.js
process(options, compiler) {
       //...
	compiler.apply(new EntryOptionPlugin());
	compiler.applyPluginsBailResult("entry-option", options.context, options.entry);
}

appply()进行插件注册,随即触发entry-option事件。


"use strict";

const SingleEntryPlugin = require("./SingleEntryPlugin");
const MultiEntryPlugin = require("./MultiEntryPlugin");
const DynamicEntryPlugin = require("./DynamicEntryPlugin");

module.exports = class EntryOptionPlugin {
	apply(compiler) {
		compiler.plugin("entry-option", (context, entry) => {
			function itemToPlugin(item, name) {
				if(Array.isArray(item)) {
					return new MultiEntryPlugin(context, item, name);
				} else {
					return new SingleEntryPlugin(context, item, name);
				}
			}
			if(typeof entry === "string" || Array.isArray(entry)) {
				compiler.apply(itemToPlugin(entry, "main"));
			} else if(typeof entry === "object") {
				Object.keys(entry).forEach(name => compiler.apply(itemToPlugin(entry[name], name)));
			} else if(typeof entry === "function") {
				compiler.apply(new DynamicEntryPlugin(context, entry));
			}
			return true;
		});
	}
};
    //SingleEntryPlugin.js
     apply(compiler) {
		compiler.plugin("compilation", (compilation, params) => {
			const normalModuleFactory = params.normalModuleFactory;

			compilation.dependencyFactories.set(SingleEntryDependency, normalModuleFactory);
		});

		compiler.plugin("make", (compilation, callback) => {
			const dep = SingleEntryPlugin.createDependency(this.entry, this.name);
			compilation.addEntry(this.context, dep, this.name, callback);
		});
	}

 

dependency

build模块时遍历AST收集dependency,dependency分为3种类型:dependencies、blocks、variables。 Dependency子类继承结构如下:

blocks即AsyncDependenciesBlock类型,用于分离异步模块,其本身同Module一样都继承自DependenciesBlock。

从options.entry开始到其依赖链上的解析是由dependency驱动,先有dependency再有模块,比如在这里构建从SingleEntryDependency开始的,然后创建该依赖关联的模块,创建依赖后再解析该模块的依赖,再从依赖到模块,因此是先有依赖再有模块。构建module流程如下:

架构设计

大家之所以认为 Webpack 复杂,很大程度上是因为它依附着一套庞大的生态系统。其实 Webpack 的核心流程远没有我们想象中那么复杂,甚至只需百来行代码就能完整复刻出来。 打包过程中也有一些特定的时机需要处理,比如:

  • 在打包前需要校验用户传过来的参数,判断格式是否符合要求
  • 在打包过程中,需要知道哪些模块可以忽略编译,直接引用 cdn 链接
  • 在编译完成后,需要将输出的内容插入到 html 文件中
  • 在输出到硬盘前,需要先清空 dist 文件夹
  • ...

这个时候需要一个可插拔的设计,方便给社区提供可扩展的接口 —— Plugin 系统

Plugin 系统 本质上就是一种事件流的机制,到了固定的时间节点就广播特定的事件,用户可以在事件内执行特定的逻辑,类似于生命周期:

我们需要建立一套事件流的机制来管控整个打包过程,大致可以分为三个阶段:

  • 打包开始前的准备工作
  • 打包过程中(也就是编译阶段)
  • 打包结束后(包含打包成功和打包失败)

这其中又以编译阶段最为复杂,另外还考虑到一个场景:watch mode]当文件变化时,将重新进行编译),因此这里最好将编译阶段(也就是compilation)单独解耦出来。compilation编译阶段分离出来,是为了解耦和复用。 在 Webpack 源码中,compiler 就像是一个大管家,它就代表上面说的三个阶段,在它上面挂载着各种生命周期函数,而 compilation 就像专管伙食的厨师,专门负责编译相关的工作,也就是打包过程中这个阶段。画个图帮助大家理解:

大致架构定下后,那现在应该如何实现这套事件流呢? 这时候就需要借助 Tapable的库,专注于自定义事件的触发和处理。通过 Tapable 我们可以注册自定义事件,然后在适当的时机去执行自定义事件。 类比到 Vue 和 React 框架中的生命周期函数,它们就是到了固定的时间节点就执行对应的生命周期,tapable 做的事情就和这个差不多,我们可以通过它先注册一系列的生命周期函数,然后在合适的时间点执行。 代码中的类:Compiler类,Compilation类,NormalModuleFactory类,NormalModule类,Dependency类,Chunk类,Parser类,MainTemplate类等。其中Compiler类和Compilation类这两个类确定了主要框架。Compiler类是webpack的最上层的管理整个生命周期的类,作用于webpack的整个生命流程。通过发布订阅者模式消息通信。Compilation类在compiler事件make触发后使用生成compilaition对象,用于存储打包编译的模块数据和处理编译模块。NormalModule类,Dependency类,Chunk类为数据类,Parser类,MainTemplate类为工具类。

构建流程

原文:https://juejin.cn/post/7392066728438136882

标签:架构设计,webpack2,name,源码,new,entry,options,打包,compiler
From: https://blog.csdn.net/gaotlantis/article/details/140467599

相关文章

  • HAL库源码移植与使用之FSMC (例子加思路与理解,万字良心保证你能听懂)
    FMC和FSMC是一样的东西,只是FMC更可控地址更多又可以驱动SDRAM,用法都一样!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!总结:其实fsmc更像是一个有着特定转换时序功能的寄存器,每个fsmc映射在芯片内存里的地址都有一个这样的寄存器,你往这个映射的地址里赋值,这个赋值信息先到达对应fsmc寄存器,他不会像普通寄存器一样直接控制......
  • HAL库源码移植与使用之驱动LCD屏
    LCD屏会有烧屏残影的风险,但因其价格便宜他非常适合用于单片机显示显示屏分为以下几种:他的组成部包含玻璃基板、背光、驱动IC等LCD接口的种类MCU很简单,连51单片机都能驱动,但无法频繁刷新,一般有着20几个引脚引出的就是MCU接口我们常用的是就是MCU,下面讲的也是LCD屏幕MCU驱动......
  • HAL库源码移植与使用之正点原子OLED使用解析
    正点原子的OLED是使用SSD1306来驱动的,并设计了多种通讯方式,通过背后的焊点来选择这里以正点原子开发板最常用的8080并口通讯来讲引脚定义各正点原子开发板对OLED的接线8080时序图发送数据示例代码voidoled_wr_byte(uint8_tdata,uint8_tcmd){ OLED_RS(cmd); /......
  • 基于Java+SpringBoot+Vue的创新创业教育中心项目申报管理系统的设计与开发(源码+lw+部
    文章目录前言项目背景介绍技术栈后端框架SpringBoot前端框架Vue数据库MySQL(MyStructuredQueryLanguage)具体实现截图详细视频演示系统测试系统测试目的系统功能测试系统测试结论代码参考数据库参考源码获取前言......
  • 基于web的宠物商城设计与实现 毕业论文终稿+初稿+修改版论文+开题报告+答辩PPT+论文检
    !!!有需要的小伙伴可以通过文章末尾名片咨询我哦!!! ......
  • Springboot 校园安全通事件报告小程序-计算机毕业设计源码02445
    Springboot校园安全通事件报告小程序系统摘 要随着中国经济的飞速增长,消费者的智能化水平不断提高,许多智能手机和相关的软件正在得到更多的关注和支持。其中,校园安全通事件报告小程序系统更是深得消费者的喜爱,它的出现极大地改善了消费者的生活质量,同时,它还创造了一种快......
  • SSM豫东乡村生产信息管理系统-计算机毕业设计源码02969
     ssm豫东乡村生产信息管理系统摘要 在当前信息技术快速发展和普及的背景下,乡村地区的公共管理和农村生产活动也面临着新的挑战和需求。为了提升公共管理的效率和服务质量,以及支持农村生产的规划和组织,需要引入信息化手段来改善管理和运营。同时,随着乡村经济的发展和现代......
  • 基于Java中的SSM框架实现娱乐影视公司管理系统项目【项目源码+论文说明】
    基于Java中的SSM框架实现娱乐影视公司管理系统演示摘要电脑的出现是一个时代的进步,不仅仅帮助人们解决了一些数学上的难题,如今电脑的出现,更加方便了人们在工作和生活中对于一些事物的处理。应用的越来越广泛,通过互联网我们可以更方便地进行办公,也能够在网上就能处理很多日......
  • 基于Java中的SSM框架实现在线考试系统项目【项目源码+论文说明】
    摘要本楚水高中在线考试系统是针对目前楚水高中在线考试的实际需求,从实际工作出发,对过去的楚水高中在线考试系统存在的问题进行分析,结合计算机系统的结构、概念、模型、原理、方法,在计算机各种优势的情况下,采用目前最流行的B/S结构和java中流行的MVC三层设计模式和eclipse编辑......
  • VINS-Fusion源码逐行解析:updateLatestStates()函数与slideWindow()
    初始化并优化位姿后,接下来做的事是将这些位姿更新给上一帧,我们来看下updateLatestStates()源码:voidEstimator::updateLatestStates(){//锁定mPropagate,确保对最新状态的更新是线程安全的mPropagate.lock();//更新最新的时间戳,等于当前帧的时间戳加上时间延......