-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcache-bust.js
More file actions
187 lines (161 loc) · 5.8 KB
/
cache-bust.js
File metadata and controls
187 lines (161 loc) · 5.8 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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#!/usr/bin/env node
/**
* Unity AI Lab
* Creators: Hackall360, Sponge, GFourteen
* https://www.unityailab.com
* unityailabcontact@gmail.com
* Version: v2.1.5
*/
/**
* 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 resources
*/
function addQueryParamsToResources(html) {
// Add cache-busting to external 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}`;
}
);
// Add cache-busting to LOCAL JS files (non-hashed ones like visitor-tracking.js, age-verification.js)
html = html.replace(
/(<script[^>]+src=["'])([^"']+\.js)(["'][^>]*>)/g,
(match, prefix, url, suffix) => {
// Skip if already has query params, is external (https://), or is a Vite-hashed asset
if (url.includes('?') || url.startsWith('http') || url.includes('/assets/') || url.includes('-')) {
return match;
}
return `${prefix}${url}?v=${BUILD_HASH}${suffix}`;
}
);
// Add cache-busting to LOCAL CSS files (non-hashed ones)
html = html.replace(
/(<link[^>]+href=["'])([^"']+\.css)(["'][^>]*>)/g,
(match, prefix, url, suffix) => {
// Skip if already has query params, is external (https://), or is a Vite-hashed asset
if (url.includes('?') || url.startsWith('http') || url.includes('/assets/') || url.includes('-')) {
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 all resources (external and local)
html = addQueryParamsToResources(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. ✅ Query parameters added to local JS/CSS files');
console.log(' 6. ✅ 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);
}