webpack源码解析---addEntry

addEntry

EntryPlugin的注册

webpack会从入口开始解析依赖。

  1. WebpackOptionsApply

    new WebpackOptionsApply().process(compiler, options);
    class WebpackOptionsApply {constructor () {}process () {// 注册 EntryOptionPlugin new EntryOptionPlugin().apply(compiler);}
    }
    
  2. EntryOptionPlugin
    EntryOptionPlugin的作用是注册compiler.hooks.entryOption钩子,当钩子被触发的时候,调用EntryOptionPlugin.applyEntryOption方法注册DynamicEntryPlugin或者EntryPlugin

    class EntryOptionPlugin {apply(compiler) {compiler.hooks.entryOption.tap("EntryOptionPlugin", (context, entry) => {// 调用静态方法 applyEntryOptionEntryOptionPlugin.applyEntryOption(compiler, context, entry);return true;});}static applyEntryOption(compiler, context, entry) {if (typeof entry === "function") {// 动态入口const DynamicEntryPlugin = require("./DynamicEntryPlugin");new DynamicEntryPlugin(context, entry).apply(compiler);} else {// 普通入口const EntryPlugin = require("./EntryPlugin");for (const name of Object.keys(entry)) {               for (const entry of desc.import) {new EntryPlugin(context, entry, options).apply(compiler);}}}}
    }
    
  3. EntryPlugin

    • 订阅了compiler.hooks.compilation钩子,触发时设置EntryDependency的ModuleFactory normalModuleFactory工厂,这个用于创建入口模块
    • 订阅compiler.hooks.make钩子,触发的时候调用compilation.addEntry方法,将入口模块加载到factorizeQueue队列,这样依赖就启动了以入口模块为七点的模块构建流程。
    class EntryPlugin {constructor(context, entry, options) {}apply(compiler) {compiler.hooks.compilation.tap("EntryPlugin",(compilation, { normalModuleFactory }) => {compilation.dependencyFactories.set(EntryDependency,normalModuleFactory);});const { entry, options, context } = this;const dep = EntryPlugin.createDependency(entry, options);compiler.hooks.make.tapAsync("EntryPlugin", (compilation, callback) => {compilation.addEntry(context, dep, options, err => {callback(err);});});}
    }
    
  4. EntryPlugin的触发
    调用compiler.run() -> compiler.compile()方法触发compiler.hooks.make钩子,进而触发EntryPlugin钩子

class Compiler {compile(callback) {this.hooks.beforeCompile.callAsync(params, err => {this.hooks.compile.call(params);this.hooks.make.callAsync(compilation, err => {})})}
}

流程为: npm run build -> webpack -> webpack-cli -> compiler.run() -> compiler.compile() -> compiler.hooks.make.callAsync() -> EntryPlugin -> compilation.addEntry()

compilation.addEntry方法的讲解

方法参数

  1. context: 上下文目录,构建中就是当前目录的项目目录
  2. entry: 入口对象,结合EntryPlugin可以看到传入的路由,Entryplugin.createDependency方法返回值对象
  3. optionsOrName: 选项或者名字
  4. callback: entry的回调函数,用于和compiler通信进行后续的流程
class Compilation {addEntry(context, entry, optionsOrName, callback) {const options =typeof optionsOrName === "object"? optionsOrName: { name: optionsOrName };this._addEntryItem(context, entry, "dependencies", options, callback);}_addEntryItem(context, entry, target, options, callback) {}
}

方法逻辑

  1. 标准化处理options,根据optionsOrName格式化成不同的对象
  2. 调用compilation._addEntryItem()方法
compilation._addEntryItem
  • context: webpack构建上下文目录,以及项目目录
  • entry: 入口对象,上文中的EntryPlugin.createDependency()返回的EntryDependency类型的实例对象
  • target: 目标类型,用于在entryData中分类类型进行缓存的标志
  • options: webpack的配置对象或者是nameOptions对象,由compilation.addEntry标准化
  • callback: 回调函数,用于和compiler进行通信使用
class Compilation {_addEntryItem(context, entry, target, options, callback) {// 根据options是否由name属性或者是compilation.entries或者是compilation.globalEntry中尝试获取缓存的入口entryDataconst { name } = options;let entryData =name !== undefined ? this.entries.get(name) : this.globalEntry;// 没有entryData的时候,会构建entryData对象,将其缓存到compilation.entries,另外entryData.dependency设置为初始的entry入口对象if (entryData === undefined) {entryData = {dependencies: [],includeDependencies: [],options: {name: undefined,...options}};entryData[target].push(entry);this.entries.set(name, entryData);} else {// 这里不成立,先忽略}    // 触发this.hooks.addEntry钩子this.hooks.addEntry.call(entry, options);// this.addModuleTree方法this.addModuleTree(/* ... */);}
}

callback回调 => _addEntryItem的回调

addEntry(context, entry, optionsOrName, callback) {this._addEntryItem(context, entry, "dependencies", options, callback);
}

compilation.addModuleTree

  • context: 上下文,当前项目的目录
  • dependency: 依赖对象
  • contextInfo: 上下文对象
class Compilation {// ...addModuleTree({ context, dependency, contextInfo }, callback) {const Dep =  dependency.constructor;const moduleFactory = this.dependencyFactories.get(Dep);this.handleModuleCreation({factory: moduleFactory,dependencies: [dependency],originModule: null,contextInfo,context},(err, result) => {if (err && this.bail) {} else if (!err && result) {callback(null, result);} else {callback();}});}
}

执行模块以及其依赖的子模块的构建,构建工作

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/37964.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于路径长度的样条插补算法(自动驾驶和路径跟踪控制适用)

以前在做车辆跟踪控制的时候发现在针对有多个X和多个Y对应的路径插补时候,总是报错,因为MATLAB里面的interp1插补函数它要求x要唯一对应一个y,当路径以单独的x或者y来求插补时候的时候就报错。由于在使用Matlab的interp1函数进行插值时&#…

怎样才能更好地保护个人账号的安全

怎样才能更好地保护个人账号的安全 保护个人账号安全是网络安全的重要组成部分,以下是一些有效的措施来增强账号的安全性: 1. 使用强密码 复杂性:创建包含大小写字母、数字和特殊字符的密码。长度:密码至少应有12个字符长。唯一…

谈谈检测浏览器类型

前几天被问到如何检测浏览器类型,我突然发现我对此并不了解,之前的项目中也没有使用到过,只隐约记得通过一个自带的方法即可获取。所以今天特意来仔细补习一下。 核心:navigator.userAgent 1.正则表达式 2.引用外部库 3.判断浏…

【Android面试八股文】你知道什么是冷启动和热启动吗?你知道应用冷启动的全流程吗?你知道如何解决启动时候的黑白屏问题?

文章目录 一、冷启动、热启动的概念二、冷启动的流程冷启动启动流程:流程细节三、如何解决启动时候的黑白屏问题?一、冷启动、热启动的概念 在Android开发中,冷启动和热启动是两个重要的概念,它们描述了应用程序启动时不同的状态和表现: 冷启动(Cold Start): 冷启动指…

记一次kafka使用不当导致的服务器异常

一、背景 1.运维反馈服务器cpu高&#xff0c;且高达80% 2.经过排查发现kafka出现消息积压情况 3.使用的是springboot kafka框架 dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka</artifactId> </dependency…

Linux-网络安全私房菜

文章目录 前言入门基本指令篇章字符集设置cdlsdatemkdirtouch-d-m 修改主机名rmshredrename重命名mv移动tar打包与压缩打包但是不压缩打包且压缩更新包文件解压对应的包 zip压缩文件命令cat查看显示行号交互写入&#xff08;追加&#xff09;显示空行 more和lesshead和tailhead…

Android的悬浮时钟(一)

在Android&#xff0c;如果要悬浮在其他应用上方显示时钟或者其他界面的话是需要申请权限的。 首先在manifest中我们就要写自己要申请的权限SYSTEM_ALERT_WINDOW <uses-permission android:name"android.permission.SYSTEM_ALERT_WINDOW" /> 不同于请求照片或…

期末复习---程序填空

注意&#xff1a; 1.数组后移 *p *(p-1) //把前一个数赋值到后一个数的位置上来覆盖后一个数 2.指针找最大字符 max *p while( *p){ if( max< *p) { max*p; qp;/ 用新的指针指向这个已经找到的最大位置&#xff1b;!!!!!!!!! } p; //因为开始没有next &#xff…

Web工程化

1、webpack 1.1 概念 一个前端打包器。 webpack 只识别javascript. 所以需要安装nodejs环境。 1.2 运行环境 Nodejs Nodejs 是运行JavaScript的环境。 因为nodejs发布了许多版本&#xff0c;在不同的技术栈下&#xff0c;需要使用不同的nodejs。 所以需要在电脑上安装n…

web应用技术-第十一次课后作业

验证过滤器进行权限验证的原理。 Filter过滤器&#xff1a;可以把对资源的请求拦截下来&#xff0c;从而实现一些特殊的功能。一般完成登录校验、统一编码处理、敏感字符处理等通用操作。 定义&#xff1a;实现Filter接口 配置&#xff1a;WebFilter(urlPatterns"/*&qu…

常见VPS主机术语有哪些?VPS术语解析

常见VPS主机术语有哪些&#xff1f;本期为大家解析一下我们常见到的听到的VPS专业术语&#xff0c;帮助大家更轻松的了解VPS主机相关知识。 常见VPS主机术语 Apache – 世界上最流行的 Web 服务器软件。 CentOS – 旨在提供基于 Red Hat Enterprise Linux 的企业级操作系统的…

mysql 主主HA高可用方案详解

1.环境准备&#xff1a; 主机&#xff1a;1921.4,1921.5 操作系统&#xff1a;centos 7.3 mysql数据库版本&#xff1a;mysql 5.7.13 浮动IP:1921.182 2.mysql 下载及解压安装配置 2.1 下载&#xff1a; #wget http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.13-linu…

easyexcel 模板填充Excel数据,实现自定义换行及动态调整行高,并保持列表格式一致

pom依赖&#xff1a; <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.5</version> </dependency><dependency><groupId>com.alibaba</groupId><artifa…

数据结构-线性表的应用

目录 前言一、有序表的合并1.1 顺序表实现1.2 单链表实现 二、稀疏多项式的相加和相乘2.1 稀疏多项式的相加2.2 稀疏多项式的相乘 总结 前言 本篇文章介绍线性表的应用&#xff0c;分别使用顺序表和单链表实现有序表的合并&#xff0c;最后介绍如何使用单链表实现两个稀疏多项…

基于springboot+vue+uniapp的超市售货管理平台

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

考研生活day2--王道课后习题2.3.1、2.3.2、2.3.3

2.3.1 题目描述&#xff1a; 这题和曾经做过的LeetCode203.移除元素一模一样&#xff0c;所以我们就使用LeetCode进行书写&#xff0c;题目链接203. 移除链表元素 - 力扣&#xff08;LeetCode&#xff09; 解题思路 大家的第一反应肯定是根据书上所学的书写方法一样书写&…

【PB案例学习笔记】-26制作一个带浮动图标的工具栏

写在前面 这是PB案例学习笔记系列文章的第26篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gite…

爬虫cookie是什么意思

“爬虫 cookie”指的是网络爬虫在访问网站时所使用的cookie&#xff0c;网络爬虫是一种自动化程序&#xff0c;用于在互联网上收集信息并进行索引&#xff0c;这些信息可以用于搜索引擎、数据分析或其他目的。 本教程操作系统&#xff1a;Windows10系统、Dell G3电脑。 “爬虫…

51-1 内网信息收集 - 内网资源探测

导语 在内网渗透过程中,通常需要利用各种技术来探测内网资源,为后续的横向渗透做准备。发现内网存活的主机及其详细信息可以帮助确定攻击方向和潜在的漏洞。 一、基于 ICMP 发现存活主机 ICMP(Internet Control Message Protocol,因特网控制消息协议)是 TCP/IP 协议簇的…

一段式、二段式和三段式状态机的特点及适用情况:

在FPGA设计中,状态机的选择主要取决于具体应用场景和设计需求。 一段式状态机: 优点: 结构简单,易于理解和实现占用资源少时序逻辑简单,延迟小 缺点: 组合逻辑复杂度高可能存在毛刺问题不易于大规模状态机的设计 适用场景: 简单的控制逻辑状态数量较少的场合对时序要求较…