-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcache-bust.js
More file actions
executable file
Β·154 lines (131 loc) Β· 4.61 KB
/
cache-bust.js
File metadata and controls
executable file
Β·154 lines (131 loc) Β· 4.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/env node
/**
* Post-Build Cache Busting Script
* Ensures aggressive cache invalidation for GitHub Pages deployment
*
* This script runs after Vite build to add additional cache-busting measures:
* 1. Adds cache-control meta tags to HTML files
* 2. Adds build timestamp to HTML files
* 3. Ensures all external resources have cache-busting
*/
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const DIST_DIR = 'dist';
const BUILD_TIMESTAMP = new Date().toISOString();
const BUILD_HASH = crypto.createHash('md5').update(BUILD_TIMESTAMP).digest('hex').substring(0, 8);
/**
* Cache-control meta tags to add to HTML files
*/
const CACHE_CONTROL_TAGS = `
<!-- Cache Control - Prevent aggressive caching by GitHub Pages -->
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<meta name="build-timestamp" content="${BUILD_TIMESTAMP}">
<meta name="build-hash" content="${BUILD_HASH}">`;
/**
* Recursively find all HTML files in a directory
*/
function findHtmlFiles(dir) {
let htmlFiles = [];
const files = fs.readdirSync(dir);
for (const file of files) {
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
htmlFiles = htmlFiles.concat(findHtmlFiles(filePath));
} else if (file.endsWith('.html')) {
htmlFiles.push(filePath);
}
}
return htmlFiles;
}
/**
* Add cache-busting query parameters to external resources
*/
function addQueryParamsToExternalResources(html) {
// Add cache-busting to CDN resources that don't have versioning
html = html.replace(
/(<script[^>]+src=["'])(https:\/\/[^"']+)(["'][^>]*>)/g,
(match, prefix, url, suffix) => {
// Skip if URL already has query parameters or is a known versioned CDN
if (url.includes('?') || url.includes('@') || url.includes('/dist/')) {
return match;
}
return `${prefix}${url}?v=${BUILD_HASH}${suffix}`;
}
);
html = html.replace(
/(<link[^>]+href=["'])(https:\/\/[^"']+)(["'][^>]*>)/g,
(match, prefix, url, suffix) => {
// Skip if URL already has query parameters or is a known versioned CDN
if (url.includes('?') || url.includes('@') || url.includes('/dist/')) {
return match;
}
return `${prefix}${url}?v=${BUILD_HASH}${suffix}`;
}
);
return html;
}
/**
* Process a single HTML file
*/
function processHtmlFile(filePath) {
console.log(` π Processing: ${filePath}`);
let html = fs.readFileSync(filePath, 'utf8');
// Add cache-control meta tags after <head>
if (html.includes('<head>')) {
html = html.replace('<head>', `<head>${CACHE_CONTROL_TAGS}`);
} else {
console.warn(` β οΈ No <head> tag found in ${filePath}`);
}
// Add cache-busting to external resources
html = addQueryParamsToExternalResources(html);
// Add build info comment
const buildComment = `\n<!-- Built: ${BUILD_TIMESTAMP} | Hash: ${BUILD_HASH} -->\n`;
html = html.replace('</body>', `${buildComment}</body>`);
// Write back to file
fs.writeFileSync(filePath, html, 'utf8');
console.log(` β
Cache-busting applied`);
}
/**
* Main execution
*/
function main() {
console.log('π Applying aggressive cache-busting measures...');
console.log(`π
Build timestamp: ${BUILD_TIMESTAMP}`);
console.log(`π Build hash: ${BUILD_HASH}`);
console.log('');
// Check if dist directory exists
if (!fs.existsSync(DIST_DIR)) {
console.error(`β Error: ${DIST_DIR} directory not found!`);
console.error(' Make sure to run this script after Vite build.');
process.exit(1);
}
// Find all HTML files
const htmlFiles = findHtmlFiles(DIST_DIR);
console.log(`π Found ${htmlFiles.length} HTML files to process`);
console.log('');
// Process each HTML file
htmlFiles.forEach(processHtmlFile);
console.log('');
console.log('β
Cache-busting complete!');
console.log('');
console.log('Applied measures:');
console.log(' 1. β
Cache-Control meta tags (no-cache, no-store, must-revalidate)');
console.log(' 2. β
Pragma and Expires headers');
console.log(' 3. β
Build timestamp and hash in meta tags');
console.log(' 4. β
Query parameters added to external CDN resources');
console.log(' 5. β
Vite content-hashed assets (built-in)');
console.log('');
console.log('π Your site is now fully protected against aggressive caching!');
}
// Run the script
try {
main();
process.exit(0);
} catch (error) {
console.error('β Error during cache-busting:', error);
process.exit(1);
}