webpack源码分析——enhanced-resolve库之getType、normalize、join和cachedJoin函数

一、PathType 路径类型

const PathType = Object.freeze({Empty: 0, // 空Normal: 1, // 默认值Relative: 2, // 相对路径AbsoluteWin: 3, // win 下的绝对路径AbsolutePosix: 4, // posix 下的绝对路径Internal: 5 // enhanced-resolve 内部自定义的一种类型,具体是用来 escaping,具体说明:https://www.npmjs.com/package/enhanced-resolve
});

注:什么是Posix?点击查看path

函数中用到的变量定义

const path = require("path");const CHAR_HASH = "#".charCodeAt(0);
const CHAR_SLASH = "/".charCodeAt(0);
const CHAR_BACKSLASH = "\\".charCodeAt(0);
const CHAR_A = "A".charCodeAt(0);
const CHAR_Z = "Z".charCodeAt(0);
const CHAR_LOWER_A = "a".charCodeAt(0);
const CHAR_LOWER_Z = "z".charCodeAt(0);
const CHAR_DOT = ".".charCodeAt(0);
const CHAR_COLON = ":".charCodeAt(0);const posixNormalize = path.posix.normalize; 
const winNormalize = path.win32.normalize;

二、getType 函数

该函数通过传入的路径,判断并返回其类型值。返回的类型值为PathType中定义的值之一

  1. 根据传入的路径length判断
switch (p.length) {case 0:return PathType.Empty; // 当length ==0 时, 返回 PathType.Emptycase 1: {const c0 = p.charCodeAt(0);switch (c0) {case CHAR_DOT:return PathType.Relative; // 如果开头的第一个字符为‘.’时,返回PathType.Relativecase CHAR_SLASH:return PathType.AbsolutePosix; // 如果开头的第一个字符为‘/’时,返回PathType.AbsolutePosixcase CHAR_HASH:return PathType.Internal; // 如果开头的第一个字符为‘#’时,返回PathType.Internal}return PathType.Normal; // 没有匹配到返回兜底值PathType.Normal}case 2: {const c0 = p.charCodeAt(0);switch (c0) {case CHAR_DOT: { // 当第一个字符为‘.’const c1 = p.charCodeAt(1);switch (c1) {case CHAR_DOT:case CHAR_SLASH:return PathType.Relative; // 当第二个字符为‘.’或‘/’时。返回PathType.Relative}return PathType.Normal; // 没有匹配到返回兜底值PathType.Normal}case CHAR_SLASH:return PathType.AbsolutePosix; // 当第二个字符为‘/’时。返回PathType.AbsolutePosixcase CHAR_HASH:return PathType.Internal; // 当第二个字符为‘#’时。返回PathType.Internal}const c1 = p.charCodeAt(1);if (c1 === CHAR_COLON) {  // 判断是否时win平台if ((c0 >= CHAR_A && c0 <= CHAR_Z) ||(c0 >= CHAR_LOWER_A && c0 <= CHAR_LOWER_Z)) {return PathType.AbsoluteWin; // 是 win 返回PathType.AbsoluteWin}}return PathType.Normal; // 没有匹配到返回兜底值PathType.Normal}}
  1. 当路径length大于2时
	const c0 = p.charCodeAt(0); // 获取第一个字符switch (c0) {case CHAR_DOT: {const c1 = p.charCodeAt(1);switch (c1) {case CHAR_SLASH:return PathType.Relative; // 当第一个字符为‘.’第二个字符为‘/’时,返回PathType.Relativecase CHAR_DOT: {const c2 = p.charCodeAt(2);if (c2 === CHAR_SLASH) return PathType.Relative; // 当第一个字符为‘.’第二个字符为‘.’和第三个字符为‘/’时,返回PathType.Relativereturn PathType.Normal; // 没有匹配到返回兜底值PathType.Normal}}return PathType.Normal;// 没有匹配到返回兜底值PathType.Normal}case CHAR_SLASH:return PathType.AbsolutePosix; // 当第一个字符为‘/’时,返回PathType.AbsolutePosixcase CHAR_HASH:return PathType.Internal;// 当第一个字符为‘#’时,返回PathType.Internal}const c1 = p.charCodeAt(1);if (c1 === CHAR_COLON) { // 判断是否在win下,并且为绝对路径const c2 = p.charCodeAt(2);if ((c2 === CHAR_BACKSLASH || c2 === CHAR_SLASH) &&((c0 >= CHAR_A && c0 <= CHAR_Z) ||(c0 >= CHAR_LOWER_A && c0 <= CHAR_LOWER_Z))) {return PathType.AbsoluteWin;}}return PathType.Normal;// 没有匹配到返回兜底值PathType.Normal

例1:win上的绝对路径
请添加图片描述
例2:posix上的绝对路径
请添加图片描述

三、normalize函数

该函数通过调用node的path.normalize方法规范化给定的 path

  1. 对传入的路径调用getType函数根据返回值,对Empty、AbsoluteWin和Relative三种类型进行处理
    switch (getType(p)) {case PathType.Empty:case PathType.AbsoluteWin:case PathType.Relative: 
    }
    
  2. 当为路径类型为PathType.Empty
    return p; // 直接返回
    
  3. 当为路径类型为PathType.AbsoluteWin
    return winNormalize(p); // path.win32.normalize
    
  4. 当为路径类型为PathType.Relative
    const r = posixNormalize(p); // path.posix.normalize
    return getType(r) === PathType.Relative ? r : `./${r}`; // 因为 ‘./webpack’ 这样的路径被 posixNormalize 函数处理后 变为 ‘webpack’,所有需要这一行进行特殊处理
    

源码

const normalize = p => {switch (getType(p)) {case PathType.Empty:return p;case PathType.AbsoluteWin:return winNormalize(p);case PathType.Relative: {const r = posixNormalize(p);return getType(r) === PathType.Relative ? r : `./${r}`;}}return posixNormalize(p);
};

四、join函数

该函数进行路径进行拼接

  1. 如果 request 变量没有传入
    if (!request) return normalize(rootPath); // 直接调用normalize 函数返回
    
  2. 根据rootPath和request类型判断
    const requestType = getType(request); // 首先判断 requestType 类型
    switch (requestType) { // 如果时绝对路径,就不需要拼接了,直接调用 posixNormalize/winNormalize  返回case PathType.AbsolutePosix:return posixNormalize(request);case PathType.AbsoluteWin:return winNormalize(request);
    }
    switch (getType(rootPath)) { // 判断 rootPath 类型,上面 request 类型已经排除了绝对路径的情况,所有判断 rootPath 类型后直接和request进行拼接case PathType.Normal:case PathType.Relative:case PathType.AbsolutePosix:return posixNormalize(`${rootPath}/${request}`);case PathType.AbsoluteWin:return winNormalize(`${rootPath}\\${request}`);
    }
    /*** request 类型不为 AbsolutePosix和AbsoluteWin* rootPath 类型不为 Normal、Relative、AbsolutePosix和AbsoluteWin时* 进入下面阶段*/
    switch (requestType) {case PathType.Empty: // request 为空时(这里不存在因为在函数顶部已经错了空的判断),直接返回 rootPath。但是 rootPath 也有可能为空return rootPath;case PathType.Relative: {const r = posixNormalize(rootPath);return getType(r) === PathType.Relative ? r : `./${r}`;}
    }
    
  3. 兜底
    return posixNormalize(rootPath);
    

源码

const join = (rootPath, request) => {if (!request) return normalize(rootPath);const requestType = getType(request);switch (requestType) {case PathType.AbsolutePosix:return posixNormalize(request);case PathType.AbsoluteWin:return winNormalize(request);}switch (getType(rootPath)) {case PathType.Normal:case PathType.Relative:case PathType.AbsolutePosix:return posixNormalize(`${rootPath}/${request}`);case PathType.AbsoluteWin:return winNormalize(`${rootPath}\\${request}`);}switch (requestType) {case PathType.Empty:return rootPath;case PathType.Relative: {const r = posixNormalize(rootPath);return getType(r) === PathType.Relative ? r : `./${r}`;}}return posixNormalize(rootPath);
};

五、cachedJoin函数

该函数在 join 函数的基础上加上缓存

  1. 判断 rootPath 是否在缓存中
    const joinCache = new Map();let cache = joinCache.get(rootPath); // 从 map 中获取 rootPath
    if (cache === undefined) { // rootPath 没有在缓存中joinCache.set(rootPath, (cache = new Map())); // 新增缓存
    } else {cacheEntry = cache.get(request); // 在缓存中,根据request获取rootPath对应缓存的值if (cacheEntry !== undefined) return cacheEntry;
    }
    cacheEntry = join(rootPath, request);
    cache.set(request, cacheEntry); // 没有在缓存中时,对当前路径进行缓存
    return cacheEntry;
    

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

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

相关文章

小程序AI智能名片S2B2C商城系统:做内容、造IP、玩社群打造私域流量的新营销秘籍

在数字化浪潮汹涌的新时代&#xff0c;小程序AI智能名片S2B2C商城系统正以其独特的魅力&#xff0c;引领着营销领域的新变革。这套系统不仅将人工智能与小程序技术完美结合&#xff0c;更通过创新的S2B2C模式&#xff0c;为企业打开了一扇通往成功的大门。 面对激烈的市场竞争&…

SQL注入作业

目录 一、万能密码和二阶注入测试 1.万能密码 2.二阶注入测试 二、联合查询注入测试 1.判断注入点 2.判断当前查询语句的列数 3.查询数据库基本信息 4.查询数据库中的数据 三、报错注入 1. 报错注入函数EXTRATVALUE 2.UPDATEXML 四、盲注测试 1.布尔盲注 判断数据…

Linux搭建Discuz论坛

搭建一个论坛 —接上篇博客 改名/etc/httpd/conf.d/vhosts.conf 》/etc/httpd/conf.d/vhosts.conf.bak [rootlocalhost conf.d]# mv /etc/httpd/conf.d/vhosts.conf /etc/httpd/conf.d/vhosts.conf.bak此时的vhosts.conf是一个新创建的文件&#xff0c;之前的vhosts.conf已经…

使用 Godot 游戏引擎为 Apple 的 visionOS 创建游戏和应用的平台

借助GodotVision ,您可以使用Godot 游戏引擎为 Apple VisionOS创建游戏和应用程序。 保卫牛城堡,一款使用 GodotVision 制作的 VisionOS 游戏 GodotVision 运行一个控制本机RealityKit 视图的无头 Godot实例。粗略地说:Godot 是后端,

毅速3D打印随形透气钢:革新传统,引领未来

透气钢&#xff0c;这种多孔金属材料&#xff0c;既融合了金属材料的坚固性&#xff0c;又具备了透气材料的通透性。尤其在注塑模具的制造中&#xff0c;透气钢的作用不可忽视。通过镶嵌透气钢&#xff0c;能够有效解决因困气产生的注塑问题&#xff0c;使成型加工更为完善&…

机器学习鸢尾花使用csv

操作流程 下载鸢尾花数据集导入需要的包读取数据并查看数据大小和长度划分训练集和测试集使用模型评估算法 下载鸢尾花数据集 链接&#xff1a;https://pan.baidu.com/s/1RzZyXsaiJB3e611itF466Q?pwdj484 提取码&#xff1a;j484 --来自百度网盘超级会员V1的分享导入需要…

矩阵混乱度(熵值)代码计算

1、先回顾下熵值的数据公式&#xff1a; 2、jax.numpy代码 注意的点&#xff1a;熵值计算的输入的必须是归一化的正值 import jax.numpy as jnp import jax def _entroy(probs):log_probs jnp.log2(jnp.maximum(1.0e-30, probs))mean_sum_plogp jnp.mean(- jnp.sum(log_pro…

vscode+vue开发常用插件整理

前言&#xff1a; vscode新机开发常用插件整理 1、chinese 简体中文配置 2、file-jump 别名跳转&#xff0c;可以把引入的组件&#xff0c;通过ctrl地址名 跳转组件内部 3、Vue Peek&#xff1a;vue项目中的一些配置&#xff0c;安装后&#xff0c;能实现 ctrl组件名 跳转…

Golang图像处理实战:image/png包的应用详解

Golang图像处理实战&#xff1a;image/png包的应用详解 介绍基本操作读取PNG文件保存PNG文件 处理图像数据修改图像像素图像裁剪和缩放 高级功能使用 image/color 处理颜色优化PNG性能 错误处理与调试常见错误及其解决方法文件无法打开图像解码失败 使用工具和库进行调试 结语 …

测试数据整理--chatgpt 构造sql语句导出数据库数据

在测试过程中&#xff0c;我们有时候需要准备一些测试数据&#xff0c;若从系统中直接导出Excel数据&#xff0c;数据往往庞大且需要整合&#xff0c;不好整理&#xff0c;于是我们直接去数据库中查询一些表&#xff0c;数据整合后直接导出结果会更方便。 我们今天就 用 chatg…

shell 调用钉钉通知

使用场景&#xff1a;机器能访问互联网&#xff0c;运行时间任务后通知使用 钉钉建立单人群 手机操作&#xff0c;只能通过手机方式建立单人群 电脑端 2. 配置脚本 #!/bin/bash set -e## 上图中 access_token字段 TOKEN KEYWORDhello # 前文中设置的关键字 function call_…

【jinja2】模板渲染

HTML文件 return render_template(index.html)h1: 一级标题 变粗变大&#xff08;狗头

B02、JVM调优案例

1、调优的基本问题 1.1、为什么要调优&#xff1f; 目的是防止出现OOM&#xff0c;进行JVM规划和预调优&#xff1b;解决程序运行中各种OOM&#xff1b;以及减少Full GC出现的频率&#xff0c;解决运行慢、卡顿问题。 1.2、调优的大方向 合理的编写代码&#xff0c;充分并合理…

大气的免费wordpress模板

国产的wordpress模板&#xff0c;更适合中国人使用习惯&#xff0c;更符合中国老板的审美的大气wordpress企业官网建站模板。 WordPress模板&#xff0c;也称为主题&#xff0c;是用于定义WordPress网站或博客外观和功能的预设计文件集。这些模板使用HTML、CSS和PHP代码构建&a…

鸢尾花数据集的KNN探索与乳腺癌决策树洞察

鸢尾花数据集的KNN探索与乳腺癌决策树洞察 今天博主做了这个KNN和决策树的实验。 一.数据集介绍 介绍一下数据集&#xff1a; 威斯康星州乳腺癌数据集&#xff1a; 威斯康星州乳腺癌数据集&#xff08;Wisconsin Breast Cancer Dataset&#xff09;是一个经典的机器学习数…

【简单介绍下Beego框架】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

探索 Nacos反序列化漏洞CNVD-2023-45001

在软件开发领域&#xff0c;安全漏洞是一项不容忽视的重要问题。最近&#xff0c;我们的安全团队发现了一个影响到我们的Nacos 2.1.0版本的反序列化漏洞&#xff0c;可能带来严重的安全威胁。我们已经立即采取了修复措施。本文将深入探讨这些漏洞的原理、可能造成的影响&#x…

MySQL数据库-优化慢查询

1、什么是慢查询&#xff1f; 慢查询就是SQL执行时间过长&#xff0c;严重影响用户体验的SQL查询语句。当它频繁出现时数据库的性能和稳定性都会受到威胁 慢查询是数据库性能瓶颈的常见原因&#xff0c;是指SQL执行时间超过阈值&#xff1b;可能由于复杂的连接、缺少索引、不恰…

Linux给磁盘扩容(LVM方式)

Linux给磁盘扩容&#xff08;LVM方式&#xff09; 最近测试性能&#xff0c;在本地打数据时&#xff0c;发现磁盘空间不足&#xff0c;于是想手动给/挂载点添加空间。这里介绍通过LVM方式快速给磁盘扩容。 LVM:是一种技术&#xff0c;方便管理磁盘。如果不用LVM&#xff0c;那…

XSS漏洞---类型+实战案例+防止

文章目录 目录 文章目录 一.XSS漏洞简介 二.XSS漏洞类型 三.实战案例 反射型XSS 存储型XSS 四.防护措施 一.XSS漏洞简介 XSS漏洞&#xff08;Cross-Site Scripting&#xff09;是一种常见的Web应用程序安全漏洞&#xff0c;它允许攻击者在受害者的浏览器中注入恶意脚本。当受…