- Introduce cache busting (to circumvent aggressive caching on iOS - but ideal in other contexts as well)
- Change the build process to allow cache busting - Optimisations to the build process - Several improvements of UI geared towards mobile experience -
This commit is contained in:
12
nginx/frontend_src/entries/chat-client.html
Normal file
12
nginx/frontend_src/entries/chat-client.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Chat Client Entry</title>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Minimal HTML entry used solely for Parcel to produce hashed JS/CSS bundles. -->
|
||||
<script type="module" src="../js/chat-client.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
12
nginx/frontend_src/entries/main.html
Normal file
12
nginx/frontend_src/entries/main.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Main Entry</title>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Minimal HTML entry used solely for Parcel to produce hashed JS/CSS bundles. -->
|
||||
<script type="module" src="../js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -62,6 +62,12 @@ http {
|
||||
alias /etc/nginx/static/;
|
||||
}
|
||||
|
||||
# Long-term caching for hashed assets built by Parcel
|
||||
location ^~ /static/dist/ {
|
||||
alias /etc/nginx/static/dist/;
|
||||
add_header Cache-Control "public, max-age=31536000, immutable" always;
|
||||
}
|
||||
|
||||
#error_page 404 /404.html;
|
||||
|
||||
# redirect server error pages to the static page /50x.html
|
||||
|
||||
1357
nginx/package-lock.json
generated
1357
nginx/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -38,14 +38,25 @@
|
||||
"scripts": {
|
||||
"prebuild": "mkdir -p static/dist && npm run sync-assets",
|
||||
"sync-assets": "rsync -av ../eveai_app/static/assets/ static/assets/ && rsync -av ../eveai_chat_client/static/assets/ static/assets/",
|
||||
"build": "npm run prebuild && npm run build:main && npm run build:chat",
|
||||
"build:main": "parcel build frontend_src/js/main.js --dist-dir static/dist --public-url /static/dist/ --no-source-maps",
|
||||
"build:chat": "parcel build frontend_src/js/chat-client.js --dist-dir static/dist --public-url /static/dist/ --no-source-maps",
|
||||
"build": "npm run prebuild && npm run build:main && npm run build:chat && npm run postbuild",
|
||||
"build:main": "NODE_ENV=production parcel build frontend_src/entries/main.html",
|
||||
"build:chat": "NODE_ENV=production parcel build frontend_src/entries/chat-client.html",
|
||||
"predev": "mkdir -p static/dist && npm run sync-assets",
|
||||
"dev": "npm run predev && parcel frontend_src/js/main.js --dist-dir static/dist --public-url /static/dist/ & parcel frontend_src/js/chat-client.js --dist-dir static/dist --public-url /static/dist/",
|
||||
"prewatch": "mkdir -p static/dist && npm run sync-assets",
|
||||
"watch": "npm run prewatch && parcel watch frontend_src/js/main.js --dist-dir static/dist --public-url /static/dist/ & parcel watch frontend_src/js/chat-client.js --dist-dir static/dist --public-url /static/dist/",
|
||||
"clean": "rm -rf static/dist/* static/assets .parcel-cache"
|
||||
"clean": "rm -rf static/dist/* static/assets .parcel-cache",
|
||||
"postbuild": "node scripts/generate-manifest.mjs"
|
||||
},
|
||||
"targets": {
|
||||
"default": {
|
||||
"context": "browser",
|
||||
"distDir": "static/dist",
|
||||
"publicUrl": "/static/dist/",
|
||||
"outputFormat": "esmodule",
|
||||
"isLibrary": false,
|
||||
"optimize": true,
|
||||
"sourceMap": false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
55
nginx/scripts/generate-manifest.mjs
Normal file
55
nginx/scripts/generate-manifest.mjs
Normal file
@@ -0,0 +1,55 @@
|
||||
import { promises as fs } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
const DIST_DIR = path.resolve(process.cwd(), 'static', 'dist');
|
||||
const OUT_FILE = path.join(DIST_DIR, 'manifest.json');
|
||||
|
||||
const LOGICAL_ENTRIES = [
|
||||
{ key: 'dist/chat-client.js', base: 'chat-client', exts: ['.js'] },
|
||||
{ key: 'dist/chat-client.css', base: 'chat-client', exts: ['.css'] },
|
||||
// Optionally include main entries if referenced via templates in the future
|
||||
{ key: 'dist/main.js', base: 'main', exts: ['.js'] },
|
||||
{ key: 'dist/main.css', base: 'main', exts: ['.css'] },
|
||||
];
|
||||
|
||||
function isHashedFile(file, base, ext) {
|
||||
return file.startsWith(base + '.') && file.endsWith(ext) && file !== base + ext;
|
||||
}
|
||||
|
||||
async function generate() {
|
||||
const files = await fs.readdir(DIST_DIR);
|
||||
const manifest = {};
|
||||
|
||||
for (const entry of LOGICAL_ENTRIES) {
|
||||
const matches = [];
|
||||
for (const ext of entry.exts) {
|
||||
for (const f of files) {
|
||||
if (isHashedFile(f, entry.base, ext)) {
|
||||
matches.push(`dist/${f}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (matches.length === 1) {
|
||||
manifest[entry.key] = matches[0];
|
||||
} else if (matches.length > 1) {
|
||||
const stats = await Promise.all(
|
||||
matches.map(async m => ({
|
||||
file: m,
|
||||
mtime: (await fs.stat(path.join(DIST_DIR, path.basename(m)))).mtimeMs,
|
||||
}))
|
||||
);
|
||||
stats.sort((a, b) => b.mtime - a.mtime);
|
||||
manifest[entry.key] = stats[0].file;
|
||||
} else {
|
||||
manifest[entry.key] = entry.key; // fallback zodat pagina niet breekt
|
||||
}
|
||||
}
|
||||
|
||||
await fs.writeFile(OUT_FILE, JSON.stringify(manifest, null, 2), 'utf8');
|
||||
console.log(`[manifest] written: ${OUT_FILE}`);
|
||||
}
|
||||
|
||||
generate().catch(err => {
|
||||
console.error('[manifest] generation failed:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user