webpack hash-chunkhash-contenthash 的区别以及使用场景

如果你是一名前端开发者,那么你一定对 webpack 不陌生。webpack 是一款强大的前端打包工具,可以帮助我们打包和管理各种前端资源,使得项目更加可维护和可靠。在使用 webpack 进行打包时,你会经常听到三个名词:hash、chunkhash 和 contenthash。这三个名词都涉及到打包后文件名的命名规则,但是它们各自的意义和使用场景却存在着差别。

hash

首先我们来看一下 hash。在 webpack 的打包过程中,如果我们想要生成一个唯一的文件名,那么我们可以使用 hash。每当文件内容发生改变时,hash 的值也会发生改变。使用 hash 作为文件名的好处是,能够保证打包后的文件名唯一,从而防止浏览器缓存的问题。

举个例子,假设我们有一个入口文件 main.js,它包含了一个 div 元素,并给它设置了一个背景图像。我们的 webpack.config.js 文件如下所示:

----- ---- - ----------------
----- ----------------- - -------------------------------

-------------- - -
  ------ ----------------
  ------- -
    --------- ----------------
    ----- ----------------------- -------
  --
  -------- -
    --- -------------------
      ------ -------- ---- ------
      --------- ------------------
    --
  -
--

在上述配置中,我们在 output.filename 中使用了 [hash],表示生成唯一的文件名。当我们运行 webpack 后,生成的文件名为 app.f9c38f7fe73ea907d036.js。这里的 f9c38f7fe73ea907d036 就是本次打包的 hash 值。

在正式应用中,我们可以使用 MiniCssExtractPlugin 来提取 CSS 文件。使用 css-loader 和 style-loader 的时候也可使用以下的参数来生成 hash 名称的文件:

-
  ----- ----------
  ---- -
    ----------------------------
    -
      ------- -------------
      -------- -
        -------- -----
      -
    -
  -
--

上述代码中,使用了 MiniCssExtractPlugin.loader 从样式中提取 CSS,并使用了 options: { modules: true } 来启用 CSS Modules。最终生成的 CSS 文件名将会是一个包含 hash 值的唯一文件名。

需要注意的是,每一次打包后,所有打包后的文件,均会生成新的 hash 值。当我们不修改任何文件,再次打包时,也会生成不同的 hash 值。这是因为我们每次打包后的文件名都是唯一的,所以即使文件不变,我们生成的 hash 值也会发生变化。这样会导致在浏览器中缓存的文件因名字不同而被重新下载。

总结一下,使用 hash 可以通过修改文件名保证文件的唯一性,从而避免浏览器缓存的问题。但也正因为如此,如果我们只是改动了一个文件,那么所有文件的文件名都会改变。这种情况对于大型应用来说,会造成很多不必要的重复下载。

chunkhash

接下来我们来看 chunkhash。我们知道,当我们使用 webpack 进行打包时,打包后的文件可能会被分成多个块(chunk),例如入口代码块、异步加载代码块等。为了防止每次打包时所有文件的 hash 值都改变,我们可以使用 chunkhash。

chunkhash 的原理是,对于每一个 chunk,它都有自己的一个唯一 hash。当该 chunk 的内容发生变化时,它的 hash 值会改变,而其他 chunk 的 hash 值则不变。使用 chunkhash 作为文件名的好处是,只有发生改变的 chunk 的文件名会发生改变,其他 chunk 的文件名都不会改变。这样我们就可以通过模块热替换等技术实现部分打包和增量更新。

举个例子,假设我们项目中有两个入口文件:main.js 和 vendor.js。我们的 webpack.config.js 文件如下所示:

----- ---- - ----------------
----- ----------------- - -------------------------------

-------------- - -
  ------ -
    ----- ----------------
    ------- -----------------
  --
  ------- -
    --------- ------------------------
    ----- ----------------------- -------
  --
  -------- -
    --- -------------------
      ------ -------- --------- ------
      --------- ------------------
    --
  -
--

在上述配置中,我们在 output.filename 中使用了 [chunkhash],表示生成唯一的文件名。当我们运行 webpack 后,我们会得到两个输出文件:

  • main.js:6632c9c6e725c6d0d01c.chunk.js
  • vendor.js:89a774c74be936f1aee9.chunk.js

可以看到,main.js 和 vendor.js 分别对应了不同的 chunk,因此它们对应的 chunkhash 值也是不同的。这样当我们只修改了其中一个文件时,只有对应的 chunkhash 值会改变,而其他文件的文件名都不会发生改变。

需要注意的是,这种方法并不能完全解决潜在的缓存问题。如果我们修改了一些公共代码,例如添加一些新的函数,那么所有文件的文件名都会发生改变,这时候我们也需要重新下载这些文件。

总结一下,使用 chunkhash 可以保证只有发生改变的 chunk 的文件名会发生改变,其他文件的文件名都不会发生改变。这种方法适用于大型应用,可以实现模块热替换和增量更新。

contenthash

接下来我们来看 contenthash。使用 contenthash 的目的是保证文件名和文件内容有关系。当文件内容发生改变时,它的 contenthash 值也会发生改变。这样,即使使用了 hash 和 chunkhash 保证了唯一性和增量更新,我们也可以通过保证文件名和文件内容的关系避免文件被错误缓存的问题。

举个例子,假设我们有一个 CSS 文件 styles.css,它的内容为:

---- -
  ----------------- --------
-

我们的 webpack.config.js 文件如下所示:

----- ---- - ----------------
----- -------------------- - -----------------------------------
----- ----------------- - -------------------------------

-------------- - -
  ------ ----------------
  ------- -
    --------- ---------
    ----- ----------------------- -------
  --
  ------- -
    ------ -
      -
        ----- ---------
        ---- -
          ----------------------------
          -
            ------- -------------
            -------- -
              -------- -----
            -
          -
        -
      -
    -
  --
  -------- -
    --- ----------------------
      --------- --------------------------
    ---
    --- -------------------
      ------ -------- ----------- ------
      --------- ------------------
    --
  -
--

在上述配置中,我们在 MiniCssExtractPlugin 中使用了 [contenthash],表示生成唯一的文件名。当我们运行 webpack 后,生成的 CSS 文件名为 styles.5e5e5ce874d3f3b83d9e.css。这里的 5e5e5ce874d3f3b83d9e 就是根据文件内容生成的 contenthash 值。

需要注意的是,contenthash 的使用场景并不是很多。通常我们只需要使用 hash 和 chunkhash 就可以满足大部分需求。只有当我们对文件名和文件内容的对应关系有着特殊的要求,或者需要通过保证文件名和文件内容的关系来避免浏览器缓存的问题时,才需要使用 contenthash。

总结

通过本文的介绍,我们了解了 webpack 中的 hash、chunkhash 和 contenthash。这三者的使用场景和区别都十分重要,对于大型应用来说,选择合适的命名规则能够带来更佳的性能表现。我们可以根据具体需求来选择合适的命名规则,从而提高项目的可维护性和可靠性。

最后我们来看一下完整的 webpack.config.js 文件,它包含了所有三种命名规则的使用:

----- ---- - ----------------
----- -------------------- - -----------------------------------
----- ----------------- - -------------------------------

-------------- - -
  ------ -
    ----- ----------------
    ------- -----------------
  --
  ------- -
    --------- ------------------------
    ----- ----------------------- -------
  --
  ------- -
    ------ -
      -
        ----- ---------
        ---- -
          ----------------------------
          -
            ------- -------------
            -------- -
              -------- -----
            -
          -
        -
      -
    -
  --
  -------- -
    --- ----------------------
      --------- --------------------------
    ---
    --- -------------------
      ------ -------- -------------------------- ------
      --------- ------------------
    --
  -
--

现在我们已经掌握了 webpack 中的三种命名规则,希望这篇文章能够帮助你更好地使用 webpack 进行打包和管理前端资源。

来源:JavaScript中文网 ,转载请联系管理员! 本文地址:https://www.javascriptcn.com/post/65453c707d4982a6ebefdaa5


猜你喜欢

  • 在 Hapi 框架中使用 Axios 处理 API 请求

    在前端开发中,我们经常需要通过 API 请求从后端获取数据。Axios 是一个流行的 JavaScript 库,用于处理 HTTP 请求。Hapi 是一个 Node.js 框架,用于构建 Web 应用...

    1 年前
  • 在 Angular 中如何解决 GraphQL POST 错误的 JSON 语法?

    在前端开发中,GraphQL 作为一种强大的数据查询语言,被越来越多的开发者所采用。但是,由于 GraphQL 对于 JSON 语法有着严格的要求,因此在使用中可能会出现一些 JSON 语法错误。

    1 年前
  • Cypress 测试框架中的断言技巧

    Cypress是一款现代化的前端自动化测试框架,它使用简洁的JavaScript语言来编写测试用例,支持无头浏览器,能够模拟真实用户的行为,是前端测试技术中的强有力的工具。

    1 年前
  • PWA 技术实现桌面端应用托盘图标切换

    PWA(Progressive Web App)是一种新型的移动应用开发技术,它不仅可以让 Web 应用更加接近原生应用的体验,而且还可以像原生应用一样在桌面上运行。

    1 年前
  • 解决 Socket.io 传输大量数据时出现性能问题

    在前端开发中,Socket.io 是实现实时通讯的重要工具。但是当传输大量数据时,Socket.io 可能会出现性能问题,导致应用卡顿或崩溃。本文将探讨 Socket.io 传输大量数据时的性能问题,...

    1 年前
  • LESS 中使用 BEM 命名规范的技巧

    LESS 中使用 BEM 命名规范的技巧 在前端开发中,CSS 的命名规范一直是一个备受争议的话题。BEM(Block, Element, Modifier)命名规范是一种常见的CSS命名规范。

    1 年前
  • 在 Flutter 应用中使用 Material Design 组件库

    Material Design 是 Google 设计语言,为移动端和网络应用程序提供一致、逼真和着重于内容的设计体验。Flutter 提供了对 Material Design 的全面支持,可以轻松地...

    1 年前
  • 使用 Retrofit 技术发起 RESTful API 请求

    Retrofit 是一个优秀的网络请求库,非常适合在 Android 开发中使用。通过它,我们可以很方便地发起 RESTful API 请求,并且灵活地设置请求参数和处理响应结果,是很多前端开发者都非...

    1 年前
  • 使用 Chai 和 Jest 实现自动化测试的技巧

    在前端开发中,自动化测试是不可或缺的一部分。通过自动化测试,可以提高产品质量、减少代码错误、加快开发速度等好处。在自动化测试框架中,Chai 和 Jest 是两个常用的工具。

    1 年前
  • 详解 CSS Reset 中的 box-sizing 属性

    前言 在前端开发中,CSS Reset 是一个必不可少的工具,它会将各种浏览器默认的样式清除掉,以便更好地控制页面的样式。其中,box-sizing 属性便是 CSS Reset 中的一个关键属性,它...

    1 年前
  • 如何使用 ES6 中的 WeakMap 对象

    如何使用 ES6 中的 WeakMap 对象 简介 ES6 中的 WeakMap 是一种新的数据结构,类似于 Map,但它只接受对象作为键,并且键是弱引用的,这意味着当这个对象没有其他引用时,垃圾回收...

    1 年前
  • Serverless 架构中的异常处理方法详解

    随着云计算的发展,Serverless 架构越来越受到前端开发者们的青睐,它借助云服务提供商的强大技术底层,为开发者提供了更便捷的开发模式和更低的成本。 然而在 Serverless 架构中,由于开发...

    1 年前
  • 常用的 SASS 混合的使用方法和优化

    SASS 是一个基于 CSS 的预处理器,可以扩展 CSS,增加可读性和可维护性。SASS 提供了一种叫做混合(Mixins)的方法,可以在 CSS 规则中重复使用代码。

    1 年前
  • ECMAScript 2021:JS 中的新 feature -- 双冒号操作符 (::) 详解

    在 ECMAScript 2021 中,JavaScript 引入了一种新的语法特性--双冒号操作符(::)。这个新特性有什么作用呢?我们在本文中会详细介绍。 双冒号操作符的作用 双冒号操作符(::)...

    1 年前
  • Webpack DllPlugin 篇

    在现代化的 Web 开发中,使用前端框架和库已变成了一种不可避免的趋势。在使用大型框架和库的同时,前端开发人员面临一个共同的问题:打包时间变长、打包体积过大。Webpack DllPlugin 可以帮...

    1 年前
  • AngularJS:AngularJS 应用的性能调优和优化的技巧

    在使用 AngularJS 开发应用时,如何保证其性能和高效运行是非常重要的。本文将介绍有关 AngularJS 应用的性能调优和优化的技巧,以及如何实现最佳实践。

    1 年前
  • MongoDB 安装配置及启动流程全攻略

    什么是 MongoDB? MongoDB 是一个基于文档的 NoSQL 数据库,它使用 BSON(Binary JSON)格式存储数据,支持自动分片和副本集等高可用机制,具有高扩展性和性能优势,同时也...

    1 年前
  • 自定义 Web Components 中的 CSS 样式和命名空间

    Web Components 为前端开发者提供了一种可重用的组件化开发方式,使得我们的代码在不同的页面应用中具有更高的复用性和可读性。而且,Web Components 的独立性质可以保证这些组件在不...

    1 年前
  • Mongoose 中文文档更新方法实现及注意事项

    Mongoose 是一款用于 Node.js 的 MongoDB 对象建模工具,它可以在 Web 应用开发过程中将应用程序的数据存储到 MongoDB 中。在实践中,数据库中的数据是会被修改的。

    1 年前
  • ESLint 规则中的 no-alert 详解

    在前端开发中,我们常常会使用 JavaScript 编写交互性的代码。然而,某些用于调试的代码可能会给用户带来困扰,比如弹出警告框和提示框等。为了提高代码的可读性和可维护性,建议使用 ESLint 工...

    1 年前

相关推荐

    暂无文章