Implement cache busting based on version hash

This commit is contained in:
Pavel Djundik 2019-03-08 12:29:49 +02:00
parent bb28ecaff7
commit de9459dd83
5 changed files with 47 additions and 22 deletions

View file

@ -5,11 +5,12 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="preload" as="script" href="js/bundle.vendor.js">
<link rel="preload" as="script" href="js/bundle.js">
<link rel="preload" as="script" href="js/loading-error-handlers.js?v=<%- cacheBust %>">
<link rel="preload" as="script" href="js/bundle.vendor.js?v=<%- cacheBust %>">
<link rel="preload" as="script" href="js/bundle.js?v=<%- cacheBust %>">
<link rel="stylesheet" href="css/primer-tooltips.css">
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/primer-tooltips.css?v=<%- cacheBust %>">
<link rel="stylesheet" href="css/style.css?v=<%- cacheBust %>">
<link id="theme" rel="stylesheet" href="themes/<%- theme %>.css" data-server-theme="<%- theme %>">
<% _.forEach(stylesheets, function(css) { %>
<link rel="stylesheet" href="packages/<%- css %>">
@ -59,7 +60,7 @@
<p id="loading-slow">This is taking longer than it should, there might be connectivity issues.</p>
<button id="loading-reload" class="btn">Reload page</button>
</div>
<script async src="js/loading-error-handlers.js"></script>
<script async src="js/loading-error-handlers.js?v=<%- cacheBust %>"></script>
</div>
</div>
<div id="viewport"></div>
@ -68,7 +69,7 @@
<div id="image-viewer"></div>
<div id="upload-overlay"></div>
<script src="js/bundle.vendor.js"></script>
<script src="js/bundle.js"></script>
<script src="js/bundle.vendor.js?v=<%- cacheBust %>"></script>
<script src="js/bundle.js?v=<%- cacheBust %>"></script>
</body>
</html>

View file

@ -2,7 +2,7 @@
/* global clients */
"use strict";
const cacheName = "thelounge";
const cacheName = "__HASH__";
const excludedPathsFromCache = /^(?:socket\.io|storage|uploads|cdn-cgi)\//;
self.addEventListener("install", function() {
@ -10,6 +10,12 @@ self.addEventListener("install", function() {
});
self.addEventListener("activate", function(event) {
event.waitUntil(caches.keys().then((names) => Promise.all(
names
.filter((name) => name !== cacheName)
.map((name) => caches.delete(name))
)));
event.waitUntil(self.clients.claim());
});
@ -33,34 +39,30 @@ self.addEventListener("fetch", function(event) {
return;
}
const uri = new URL(url);
uri.hash = "";
uri.search = "";
event.respondWith(networkOrCache(event, uri));
event.respondWith(networkOrCache(event));
});
async function putInCache(uri, response) {
async function putInCache(request, response) {
const cache = await caches.open(cacheName);
await cache.put(uri, response);
await cache.put(request, response);
}
async function networkOrCache(event, uri) {
async function networkOrCache(event) {
try {
const response = await fetch(uri, {cache: "no-cache"});
const response = await fetch(event.request, {cache: "no-cache"});
if (response.ok) {
event.waitUntil(putInCache(uri, response));
event.waitUntil(putInCache(event.request, response));
return response.clone();
}
throw new Error(`Request failed with HTTP ${response.status}`);
} catch (e) {
// eslint-disable-next-line no-console
console.error(e.message, uri.href);
console.error(e.message, event.request.url);
const cache = await caches.open(cacheName);
const matching = await cache.match(uri);
const matching = await cache.match(event.request);
return matching || Promise.reject("request-not-in-cache");
}

View file

@ -9,6 +9,7 @@ const fs = require("fs");
const net = require("net");
const bcrypt = require("bcryptjs");
const colors = require("chalk");
const crypto = require("crypto");
let homePath;
let configPath;
@ -32,6 +33,7 @@ const Helper = {
getUserLogsPath,
setHome,
getVersion,
getVersionCacheBust,
getGitCommit,
ip2hex,
mergeConfig,
@ -89,6 +91,12 @@ function getGitCommit() {
}
}
function getVersionCacheBust() {
const hash = crypto.createHash("sha256").update(Helper.getVersion()).digest("hex");
return hash.substring(0, 10);
}
function setHome(newPath) {
homePath = expandHome(newPath);
configPath = path.join(homePath, "config.js");

View file

@ -281,7 +281,10 @@ function index(req, res, next) {
throw err;
}
res.send(_.template(file)(getServerConfiguration()));
const config = getServerConfiguration();
config.cacheBust = Helper.getVersionCacheBust();
res.send(_.template(file)(config));
});
}

View file

@ -5,6 +5,7 @@ const path = require("path");
const CopyPlugin = require("copy-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const VueLoaderPlugin = require("vue-loader/lib/plugin");
const Helper = require("./src/helper.js");
const config = {
mode: process.env.NODE_ENV === "production" ? "production" : "development",
@ -123,7 +124,17 @@ const config = {
{
from: "./client/*",
to: "[name].[ext]",
ignore: "index.html.tpl",
ignore: [
"index.html.tpl",
"service-worker.js",
],
},
{
from: "./client/service-worker.js",
to: "[name].[ext]",
transform(content) {
return content.toString().replace("__HASH__", Helper.getVersionCacheBust());
},
},
{
from: "./client/audio/*",