IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 深入源码分析 file-loader 哈希生成规则 -> 正文阅读

[数据结构与算法]深入源码分析 file-loader 哈希生成规则

我们知道,在 Webpack 中有三种哈希:

  • hash:一次 compilation 总体的哈希,只要有一个文件修改,整个哈希就会发生变化
  • chunk-hash:根据 chunk 生成的哈希,同一个 chunk 中所有文件的哈希相同
  • content-hash:根据文件内容生成的哈希

在 Vue-cli 默认 Webpack 配置中,对 JS 启用 chunk-hash,CSS 启用 content-hash,而图片和字体文件则是 hash。这样就产生一个问题,修改 JS 代码后,图片和字体的哈希是否会发生变化?

这个问题看起来有点中二,如果修改 JS 代码,导致图片、字体的哈希改变了,显然非常不合理。。但还是抱着好奇的心态去看了源码

file-loader 源码简化之后如下:

// 这里的 loader-utils 是 Webpack 暴露给 loader 的 API
import { getOptions, interpolateName } from 'loader-utils';

export default function loader(content) {
  // getOptions 方法用于获取 loader 的配置
  const options = getOptions(this);
  // 这里的 name 选项是配置中传递的
  const name = options.name || '[contenthash].[ext]';
  // interpolateName 方法可以根据 name 和 content 内容生成哈希
  // 可以保证文件内容没有发生变化的时候,文件名中的 [hash] 字段不变
  const url = interpolateName(this, name, { content });
  // 拼接文件路径
  // 这里的 __webpack_public_path__ 是 Webpack 提供的运行时的全局变量,即 publicPath
  let publicPath = `__webpack_public_path__ + ${JSON.stringify(url)}`;
  // emitFile 是 Loader Context 中的 API,告诉 Webpack 创建一个文件
  // 这样 Webpack 就会在 dist 目录下创建一个对应的文件
  this.emitFile(url, content);
  const esModule =
    typeof options.esModule !== 'undefined' ? options.esModule : true;
  // 返回一个字符串形式的 JS 模块,显然是在浏览器端执行的
  return `${esModule ? 'export default' : 'module.exports ='} ${publicPath};`;
}

// 记得加上这个,默认情况下 Webpack 会把文件内容当做 utf8 字符串处理
// 而图片是二进制的,当做 utf8 会导致图片格式错误
export const raw = true;

上面的代码完全可以正常运行。我们可以看到,file-loader 其实就做了三件事:

  • 根据给定的文件名配置和文件内容,生成带有哈希的文件路径;
  • 根据生成的文件路径,创建一个文件;
  • 最后返回一个字符串形式的 JS 模块,加载这个模块,就可以得到文件路径;

关于 Loader Context,应该有不少小伙伴都知道,例如可以使用 this.callback() 返回多个结果,使用 this.async() 指定异步 loader。这里用到的 this.emitFile() 也是 Loader Context 上的方法,用于创建一个文件。

https://webpack.docschina.org/api/loaders/#thisemitfile

但是可能大家对 loader-utils 了解得比较少,这同样也是 Webpack 暴露给 Loader 的 API,只不过这个是通过第三方库的形式引入的。

这里提一下,loader-utils 中的 getOptions 方法在 v3.2.0 中已经被移除了,Webpack5 可以从 Loader Context 的 this.getOptions 方法获取。这相当于是一个破坏性更新,file-loader 中之所以还能使用,是因为依赖版本锁定为 "loader-utils": "^2.0.0",也就是范围在 >=2.0.0 <3.0.0

从上面的代码中可以看出,生成哈希相关逻辑都在 interpolateName 这个方法里面,部分源码如下:

function interpolateName(loaderContext, name, options = {}) {
	let filename = name || "[hash].[ext]";
	const content = options.content;
	// ...
	let url = filename;
	if (content) {
	    // Match hash template
	    url = url
	      // `hash` and `contenthash` are same in `loader-utils` context
	      // let's keep `hash` for backward compatibility
	      .replace(
	        /\[(?:([^:\]]+):)?(?:hash|contenthash)(?::([a-z]+\d*))?(?::(\d+))?\]/gi,
	        (all, hashType, digestType, maxLength) =>
	          getHashDigest(content, hashType, digestType, parseInt(maxLength, 10))
	      );
    }
    // ...
}

看这边用到了 getHashDigest 方法,我们可以不用关心内部实现。源码中的正则表达式,我们使用 "[hash].[ext]" 进行实验,发现能拿到 hashcontenthash 配置信息的,只有第一个参数 all,其他都是 undefined
请添加图片描述
然而在源码中这个 all 根本就没有传给 getHashDigest 方法,传递的参数中唯一有用的参数就是 content,也就是文件内容。因此我们可以得出结论,文件名中无论配置 hash 或者 contenthash,都是等价的,实际上都是 contenthash,都是根据文件本身的内容生成的,与 Webpack 的构建过程无关。

参考

webpack 源码解析:file-loader 和 url-loader

https://github.com/webpack-contrib/file-loader

https://github.com/webpack/loader-utils

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-02-06 14:03:51  更:2022-02-06 14:04:12 
 
开发: 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/26 18:27:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码