webpack学习-6.缓存

webpack学习-6.缓存

1.前言

webpack 会在打包后生成可部署的 /dist 目录,并将打包后的内容放在此目录。一旦 /dist 目录中的内容部署到服务器上,客户端(通常是浏览器)就能够访问此服务器以获取站点及其资源。由于获取服务器资源是比较耗费时间的操作,因此浏览器使用了一种名为 缓存 的技术。命中缓存可以降低网络流量,使网站加载速度更快。然而,如果在部署资源的最新版本时没有更改资源的文件名,浏览器可能会认为它没有被更新,从而使用它的缓存版本。由于缓存的存在,当需要获取新的代码时,就会显得很棘手。

这篇指南的重点在于通过必要配置确保 webpack 编译生成的文件能够被客户端缓存;当文件内容变化后,客户端又能够请求到新的文件。

2.输出文件的文件名

更改 output.filename 中的 substitutions 以定义输出文件的名称。webpack 提供了一种称为 可替换模板字符串(substitution) 的方式,通过带括号字符串来模板化文件名。其中,[contenthash] 将根据资源内容创建唯一哈希值。当资源内容发生变化时,[contenthash] 也会发生变化。

webpack配置文件:

javascript 复制代码
  const path = require('path');
  const HtmlWebpackPlugin = require('html-webpack-plugin');

  module.exports = {
    entry: './src/index.js',
    plugins: [
      new HtmlWebpackPlugin({
       title: 'Caching',
      }),
    ],
    output: {
     filename: '[name].[contenthash].js',
      path: path.resolve(__dirname, 'dist'),
      clean: true,
    },
  };

打包构建:

感觉官网有点问题,webpack5的话,如果文件未更改的话,再次打包:

不会有新的bundle生成的。改变原文件内容再打包,

打包的哈希值改变了。

3. 提取引导模板

正如在 代码分离 中所学到的,SplitChunksPlugin 插件可以用于将模块分离到单独的 bundle 中。webpack 还提供了一个优化功能,可以使用 optimization.runtimeChunk 选项将 runtime 代码拆分为一个单独的 chunk。将其设置为 single 以便为所有 chunk 创建一个 runtime bundle:

javascript 复制代码
 const path = require('path');
  const HtmlWebpackPlugin = require('html-webpack-plugin');

  module.exports = {
    entry: './src/index.js',
    plugins: [
      new HtmlWebpackPlugin({
      title: 'Caching',
      }),
    ],
    output: {
      filename: '[name].[contenthash].js',
      path: path.resolve(__dirname, 'dist'),
      clean: true,
    },
   optimization: {
     runtimeChunk: 'single',
   },
  };

更改配置后再次构建,查看提取出来的 runtime bundle:

由于像 lodash 或 react 这样的第三方库很少像本地源代码一样频繁修改,因此通常推荐将第三方库提取到单独的 vendor chunk 中。这一步将减少客户端对服务器的请求,同时保证自身代码与服务器一致。可以通过使用 SplitChunksPlugin 示例 2 中演示的 SplitChunksPlugin 插件的 cacheGroups 选项来实现。试试在 optimization.splitChunks 添加如下 cacheGroups 参数并执行构建:

javascript 复制代码
const path = require('path');
  const HtmlWebpackPlugin = require('html-webpack-plugin');

  module.exports = {
    entry: './src/index.js',
    plugins: [
      new HtmlWebpackPlugin({
      title: 'Caching',
      }),
    ],
    output: {
      filename: '[name].[contenthash].js',
      path: path.resolve(__dirname, 'dist'),
      clean: true,
    },
    optimization: {
      runtimeChunk: 'single',
     splitChunks: {
       cacheGroups: {
         vendor: {
           test: /[\\/]node_modules[\\/]/,
           name: 'vendors',
           chunks: 'all',
         },
       },
     },
    },
  };

再次构建,然后查看新的 vendor bundle:

现在,可以看到 main 不再含有来自 node_modules 目录的 vendor 代码,并且体积减少到 412 bytes!

4.模块标识符

这一块我本地的和官网的结果也是不同的。

按理说,应该是三个文件的哈希值都发生了变化。这是因为每个 module.id 会默认基于解析顺序增加。换言之,当解析顺序发生变化,ID 也会随之改变。简要概括便是:

main bundle 会随着自身的新增内容的修改而发生变化。

vendor bundle 会随着自身的 module.id 的变化而发生变化。

manifest runtime 会因为现在包含一个新模块的引用而发生变化。

上面的第一点与最后一点都是符合预期的行为,而 vendor 的哈希值发生变化是我们要修复的。试试将 optimization.moduleIds 设置为 'deterministic':

但是我只有main bundle的哈希值有变化的。就和将 optimization.moduleIds 设置为'deterministic'的效果是一样的。

5.总结

1.输出文件的文件名:ebpack 提供了一种称为 可替换模板字符串(substitution) 的方式,通过带括号字符串来模板化文件名。其中,[contenthash] 将根据资源内容创建唯一哈希值。当资源内容发生变化时,[contenthash] 也会发生变化。解决浏览器缓存问题。

2.提取引导模板:webpack 还提供了一个优化功能,可以使用 optimization.runtimeChunk 选项将 runtime 代码拆分为一个单独的 chunk。将其设置为 single 以便为所有 chunk 创建一个 runtime bundle,可以将像 lodash 或 react 这样的第三方库很少像本地源代码一样频繁修改,因此通常推荐将第三方库提取到单独的 vendor chunk 中。

3.模块标识符:暂无学习经验

模块标识符:每个模块在 Webpack 中都有一个唯一的标识符,称为模块标识符。模块标识符用于标识和区分不同的模块。它可以是一个数字、字符串或其他类型的标识符,具体取决于模块的类型和配置。

模块标识符在 Webpack 的模块系统中具有重要的作用,它被用于:

1.模块的依赖关系管理:Webpack 根据模块之间的依赖关系来构建应用。模块标识符用于标识模块之间的依赖关系,使得 Webpack 可以正确地加载和解析模块。

2.模块的引用和访问:当一个模块被其他模块引用时,模块标识符用于唯一地标识和定位模块。通过模块标识符,Webpack 能够正确地将模块的导出内容提供给其他模块。

3.模块的哈希计算:当使用缓存和长期缓存(Long Term Caching)功能时,Webpack 使用模块标识符来计算模块的哈希值。这样,当模块内容发生变化时,它的哈希值会改变,从而触发缓存的更新或生成新的文件名。

相关推荐
livemetee6 分钟前
Flink2.0学习笔记:Flink服务器搭建与flink作业提交
大数据·笔记·学习·flink
INS_KF1 小时前
【C++知识杂记2】free和delete区别
c++·笔记·学习
Easocen1 小时前
Mybatis学习笔记(五)
笔记·学习·mybatis
海梨花2 小时前
【从零开始学习Redis】项目实战-黑马点评D2
java·数据库·redis·后端·缓存
丑小鸭是白天鹅3 小时前
嵌入式C语言学习笔记之枚举、联合体
c语言·笔记·学习
楼田莉子4 小时前
C++算法题目分享:二叉搜索树相关的习题
数据结构·c++·学习·算法·leetcode·面试
奶黄小甜包6 小时前
C语言零基础第18讲:自定义类型—结构体
c语言·数据结构·笔记·学习
rannn_1118 小时前
【MySQL学习|黑马笔记|Day7】触发器和锁(全局锁、表级锁、行级锁、)
笔记·后端·学习·mysql
喜欢吃燃面9 小时前
C++算法竞赛:位运算
开发语言·c++·学习·算法
传奇开心果编程9 小时前
【传奇开心果系列】Flet框架实现的家庭记账本示例自定义模板
python·学习·ui·前端框架·自动化