webpack系列3-持久化缓存

65 阅读2分钟

前言

下面会介绍我在工作中是如何配置 webpack 来做到持久化缓存的

可以先参考下前端开发部署

前端项目中如何上线

  • 上线前我们开的 js、css
  • 上线时候机器上保存了一个 html 引入 js css
  • 每次的变更只需要更新我们 js、css 地址即可

遇到的问题

如何保证在 js、css 在部署时候, 老用户稳定性、 新用户看到最新页面

  • 对 js、css 等文件开启缓存
  • 对 js 、css 等文件通过唯一的路径地址保证资源是增量的
  • 先上线 js、css 这些文件, 在上传 html 保证新老用户的稳定性

总之就是要保证我们 js、css 这些资源是唯一的,可以缓存的

webpack 如何做持久化缓存

玩法(hash 文件名)

  • js、css 打包后的资源地址是唯一的
  • 是稳定的,只打包当前更新模块

hash 分类

  • hash 方式:通过 webpack 在编译过程中生成唯一 hash 值,任意文件的变换都会重新生成
  • chunkhash 方式:根据模块计算的 hash 值,只对某个文件的改动来生成 hash 值

上一段 config.js 配置

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
  entry: path.resolve(__dirname, "../src/index.js"),
  output: {
    filename: "[name].[chunkhash:8].js",
    path: path.resolve(__dirname, "../dist"),
  },
  plugins: [new HtmlWebpackPlugin()],
};

验证过程

基本用法

  • 入口
console.log("入口");
// 更新

console.log("入口11");
  • 打包结果(main.b2ce5bb9e246f093f9eb.js)
  • 更新结果(main.3b628179ae3dbd2e4284.js)

分离第三库、自定义模块

  • 入口
// one.js
import React from "react";
console.log(React);

export const greeter = function () {
  var greet = document.createElement("div");
  greet.textContent = "one";
  // 更新
  // greet.textContent = "one11111";
  return greet;
};

// two.js
import React from "react";
console.log(React);

export const greeter = function () {
  var greet = document.createElement("div");
  greet.textContent = "two";
  return greet;
};

// index.js
function getComponent() {
  return import("lodash").then((_) => {
    var element = document.createElement("div");
    element.innerHTML = _.join(["Hello", "webpack"], " ");
    return element;
  });
}

getComponent().then((component) => {
  document.body.appendChild(component);
});

import("./one").then((module) => {
  const greeter = module.default;
});
import("./two").then((module) => {
  const greeter = module.default;
});
  • 打包结果
  • 更新结果

借助 webpack 的 splitChunk 做到

  • 抽离公共的模块
  • 抽离第三方模块
  • 异步加载的模块

影响 chunkhash 值变换原因

  • 更改某个模块了 chunkhash 才会变换
  • webpack 运行的 runtime 代码

css 的缓存

  • CSS 样式单独抽离生成文件

  • MiniCssExtractPlugin

    有个注意点

    • 只改变 CSS 文件,会发现对应的 entry JS 和 CSS 文件的 chunkhash 都会改变
    • CSS 文件将使用 contenthash,以区分 CSS 文件和 JS 文件的更新

小结

以上写的不太美观的地方,大家多见谅

👇🏻 实际开发中我们理想缓存策略

  • 抽离 runtime 保证 chunkhash 不会影响
  • 使用 contenthash 抽离 css 文件
  • 设置 namedChunks
  • gif|png|jpe?g|eot|woff|ttf|svg|pdf 等使用 hash