本文目标
- 让 Webpack 在 每次构建 时自动生成一个「时间戳 + Git Hash」版本号
- 在浏览器启动时对比旧版本号,自动清理本地缓存(
localStorage / indexedDB / Cache Storage
等)防止加载到过期资源- 提供从安装到验证的完整、可直接复制使用的示例代码
前端项目经过打包后,浏览器往往会把静态资源、接口数据、IndexedDB 等缓存住。如果代码更新而版本号没变,用户可能继续使用旧缓存,引发:
给应用打上 唯一且递增 的版本标识,并在运行时检测变化后清理缓存,是最简单可靠的办法。
构建阶段:
abc1234
)new Date().toISOString()
拿到 构建时间2025-05-28T14:00:12.101Z-abc1234
作为版本号DefinePlugin
把它注入成全局常量 __APP_VERSION__
webpack-version-file-plugin
输出一份 version.json
方便运维/排障运行阶段:
localStorage.app_version
# 开发依赖
npm i -D webpack webpack-cli webpack-version-file-plugin
只示例核心插件,其他如 React/Vue/处理器 loader 请保持你原有配置。
webpack.config.js
/* webpack.config.js */
const webpack = require("webpack");
const VersionFilePlugin = require("webpack-version-file-plugin");
const { execSync } = require("child_process");
function genVersion() {
const gitHash = execSync("git rev-parse --short HEAD").toString().trim();
const buildDate = new Date().toISOString();
return `${buildDate}-${gitHash}`; // e.g. 2025-05-28T14:00:12.101Z-abc1234
}
const VERSION = genVersion();
module.exports = {
// ……你自己的 entry / output / loaders
plugins: [
/* 1. 把版本号注入为全局常量 */
new webpack.DefinePlugin({
__APP_VERSION__: JSON.stringify(VERSION),
}),
/* 2. 同时产出静态文件 dist/version.json(选做,但强烈推荐)*/
new VersionFilePlugin({
outputFile: "version.json",
templateString: JSON.stringify(
{ version: VERSION, buildDate: new Date().toISOString() },
null,
2
),
}),
],
};
为什么用
DefinePlugin
?
- 构建时直接把字符串替换进代码,运行时零成本
- 任何环境(开发/生产)都能使用
- 比按需 fetch 文件简单、无需异步
/* src/utils/version-check.js */
function clearCacheIfVersionChanged() {
const current = __APP_VERSION__; // 来自 DefinePlugin
const stored = localStorage.getItem("app_version");
if (stored !== current) {
console.info("[Version] 发现新版本 → 清理本地缓存");
/* ⚠️ 按需清理,下列操作请根据项目实际开启 */
localStorage.clear(); // 简单粗暴
indexedDB?.databases?.().then(dbs => // Safari 需检查 API 支持
dbs.forEach(db => indexedDB.deleteDatabase(db.name))
);
if (caches) {
caches.keys().then(keys => keys.forEach(k => caches.delete(k)));
}
/* 更新版本号并可选刷新 */
localStorage.setItem("app_version", current);
location.reload(); // 或者提示用户手动刷新
}
}
export default clearCacheIfVersionChanged;
/* src/main.js */
import clearCacheIfVersionChanged from "./utils/version-check";
clearCacheIfVersionChanged();
/* 之后再渲染你的应用 */
import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
createRoot(document.getElementById("root")).render(<App />);
建议 最早 执行,以便在加载其他数据前就完成校验。
第一次构建
npm run build
dist/bundle.js
中出现常量 __APP_VERSION__="2025-05-28T14:00:12.101Z-abc1234"
dist/version.json
内容对应本地启动或部署后访问
localStorage.app_version
被写入同值提交新代码 → 第二次构建
git commit -m "feat: update"
npm run build
问题 | 解决思路 |
---|---|
Git 仓库为空 | git rev-parse 会报错 → 可捕获异常并仅用时间戳:try { gitHash = … } catch { gitHash = 'nogit' } |
开发模式频繁刷新 | 开发环境可禁用全量清理:if (process.env.NODE_ENV === 'production') { … } |
想用语义版本号 | 构建前执行 npm version patch 或 standard-version ,再读 require('./package.json').version |
利用 Webpack 构建钩子与浏览器存储 API,我们可以 零后端改动 地实现:
把这套机制加入 CI/CD 流程后,你再也不用担心「线上用户还在用三个月前的缓存」的尴尬场景了。祝开发顺利,版本无忧!
片外友情提醒:
一、面向未来编程
在网上或者使用ai搜索类似方案时,很多时候会给出使用webpack-auto-inject-version
、webpack-plugin-auto-version
和git-revision-webpack-plugin
这三款插件的方式。
我尝试了第一种和以后一种配置方式,一直报错,最终排查存储的原因是因为我用了最新的webpack版本5. 这两种是老版本的配置方式。大家如果遇到类似问题就直接跳过吧,不要再浪费时间去研究了。
如无必要,我实在不想去了解和学习老版本如何配置的,更不想将webpack降版本。因为我们作为程序员,永远要面向未来编程。
二、在实战中学习、积累、成长
以前我对前端知识也是一知半解,不甚了了。但是借助对我的Pocket Bookmarks 口袋书签项目,不仅让我加深了对python知识的掌握,同时也了解了前端的编程技术,更是对linux系统有了更深的体会。初次之外,对产品、设计、开发、部署、运维和运营多种工作有了长足的进步。原来在公司都是纯后端的开发,偏安一隅,眼界受制于工作的内容,思考方式也全部是后端开发的视角。通过实际的项目开发,才有易总俯瞰全局,理解每个组成部分的运行机制。每一部分都有其很深的领域知识。总之,在实战中积累经验,无疑是最快速最能让人成长。
关注我,持续带你了解技术知识,产品知识,运营知识。让我们一起成长!
谷歌浏览器插件:立即安装 Pocket Bookmarks
edge浏览器插件:立即安装Pocket Bookmarks
✨ 为什么你急需这个插件?
✔️ 3秒极简操作:无需学习成本,清爽界面一键管理
✔️ 跨设备无缝同步:电脑/手机随时存取重要链接
✔️ 黑科技AI助手:自动分类+智能推荐,比你自己更懂你的收藏习惯
✔️ 可视化数据看板:TOP10常用书签、访问趋势一目了然
效率党最爱的功能:
• 多维度分类:支持标签+文件夹双重管理
• 智能排序:按访问频率/创建时间快速筛选
• 团队协作:分类书签一键共享给同事
• 个性展示:九宫格/列表/时间轴多种视图
真实使用场景:
现在安装还能获得:
用户说:
“原来每天找书签要花10分钟,现在3秒直达!”
“AI自动打标签功能简直拯救了我的收藏夹”