mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 08:20:50 +00:00
Include Vite's bundle output in the manifest (#3772)
## Description: ## Summary Include Vite's bundle output (`vendor-*`, `index-*`, workers, CSS under `static/assets/`) in the asset manifest so the R2 deploy upload covers them alongside hashed source assets. Move the manifest from `static/_assets/asset-manifest.json` to `static/asset-manifest.json` since it now describes both trees, and update `update.sh` to extract the whole `static/` tree. ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: evan
This commit is contained in:
@@ -375,7 +375,7 @@ export function writePublicAssetManifest(
|
|||||||
outDir: string,
|
outDir: string,
|
||||||
assetManifest: AssetManifest,
|
assetManifest: AssetManifest,
|
||||||
): void {
|
): void {
|
||||||
const manifestPath = path.join(outDir, "_assets", "asset-manifest.json");
|
const manifestPath = path.join(outDir, "asset-manifest.json");
|
||||||
fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
|
fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
|
||||||
fs.writeFileSync(manifestPath, `${JSON.stringify(assetManifest, null, 2)}\n`);
|
fs.writeFileSync(manifestPath, `${JSON.stringify(assetManifest, null, 2)}\n`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import type { AssetManifest } from "../core/AssetUrls";
|
|||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = path.dirname(__filename);
|
const __dirname = path.dirname(__filename);
|
||||||
const staticDir = path.join(__dirname, "../../static");
|
const staticDir = path.join(__dirname, "../../static");
|
||||||
const manifestPath = path.join(staticDir, "_assets", "asset-manifest.json");
|
const manifestPath = path.join(staticDir, "asset-manifest.json");
|
||||||
|
|
||||||
let cachedManifest: AssetManifest | null = null;
|
let cachedManifest: AssetManifest | null = null;
|
||||||
|
|
||||||
|
|||||||
@@ -53,18 +53,19 @@ EXTRACT_DIR="$(mktemp -d -t openfront-assets-XXXXXX)"
|
|||||||
trap 'rm -rf "$EXTRACT_DIR"' EXIT
|
trap 'rm -rf "$EXTRACT_DIR"' EXIT
|
||||||
|
|
||||||
TMP_CONTAINER="$(docker create "${GHCR_IMAGE}")"
|
TMP_CONTAINER="$(docker create "${GHCR_IMAGE}")"
|
||||||
if ! docker cp "${TMP_CONTAINER}:/usr/src/app/static/_assets" "$EXTRACT_DIR/"; then
|
if ! docker cp "${TMP_CONTAINER}:/usr/src/app/static" "$EXTRACT_DIR/"; then
|
||||||
echo "❌ docker cp failed"
|
echo "❌ docker cp failed"
|
||||||
docker rm "${TMP_CONTAINER}" > /dev/null 2>&1 || true
|
docker rm "${TMP_CONTAINER}" > /dev/null 2>&1 || true
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
docker rm "${TMP_CONTAINER}" > /dev/null
|
docker rm "${TMP_CONTAINER}" > /dev/null
|
||||||
|
|
||||||
echo "Extracted to $EXTRACT_DIR; top-level contents:"
|
STATIC_DIR="$EXTRACT_DIR/static"
|
||||||
ls -la "$EXTRACT_DIR/" || true
|
echo "Extracted to $STATIC_DIR; top-level contents:"
|
||||||
|
ls -la "$STATIC_DIR/" || true
|
||||||
|
|
||||||
R2_ENDPOINT="https://api.${DOMAIN}"
|
R2_ENDPOINT="https://api.${DOMAIN}"
|
||||||
MANIFEST="$EXTRACT_DIR/_assets/asset-manifest.json"
|
MANIFEST="$STATIC_DIR/asset-manifest.json"
|
||||||
if [ ! -f "$MANIFEST" ]; then
|
if [ ! -f "$MANIFEST" ]; then
|
||||||
echo "❌ Manifest not found at $MANIFEST"
|
echo "❌ Manifest not found at $MANIFEST"
|
||||||
exit 1
|
exit 1
|
||||||
@@ -101,7 +102,7 @@ if [ -z "$MISSING" ]; then
|
|||||||
else
|
else
|
||||||
MISSING_COUNT="$(echo "$MISSING" | wc -l | tr -d ' ')"
|
MISSING_COUNT="$(echo "$MISSING" | wc -l | tr -d ' ')"
|
||||||
echo "Uploading $MISSING_COUNT missing asset(s)..."
|
echo "Uploading $MISSING_COUNT missing asset(s)..."
|
||||||
export R2_ENDPOINT API_KEY EXTRACT_DIR
|
export R2_ENDPOINT API_KEY STATIC_DIR
|
||||||
# KEY from the manifest is URL-encoded per segment (e.g. flags/C%C3%B4te.png).
|
# KEY from the manifest is URL-encoded per segment (e.g. flags/C%C3%B4te.png).
|
||||||
# Files on disk live at the *decoded* path, so decode KEY before reading the
|
# Files on disk live at the *decoded* path, so decode KEY before reading the
|
||||||
# file, then encode the whole decoded path as one URL segment for the POST.
|
# file, then encode the whole decoded path as one URL segment for the POST.
|
||||||
@@ -132,7 +133,7 @@ else
|
|||||||
"$R2_ENDPOINT/game_assets/upload/$ENC" \
|
"$R2_ENDPOINT/game_assets/upload/$ENC" \
|
||||||
-H "X-API-Key: $API_KEY" \
|
-H "X-API-Key: $API_KEY" \
|
||||||
-H "Content-Type: application/octet-stream" \
|
-H "Content-Type: application/octet-stream" \
|
||||||
--data-binary "@$EXTRACT_DIR/$DECODED" > /dev/null; then
|
--data-binary "@$STATIC_DIR/$DECODED" > /dev/null; then
|
||||||
echo "❌ Failed to upload: $DECODED" >&2
|
echo "❌ Failed to upload: $DECODED" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
+17
-1
@@ -71,13 +71,29 @@ export default defineConfig(({ mode }) => {
|
|||||||
mobileLogoImageUrl: buildAssetUrl("images/OF.png", assetManifest),
|
mobileLogoImageUrl: buildAssetUrl("images/OF.png", assetManifest),
|
||||||
};
|
};
|
||||||
|
|
||||||
const syncHashedPublicAssets = () => ({
|
let viteBundleFiles: string[] = [];
|
||||||
|
const syncHashedPublicAssets = (): Plugin => ({
|
||||||
name: "sync-hashed-public-assets",
|
name: "sync-hashed-public-assets",
|
||||||
apply: "build" as const,
|
apply: "build" as const,
|
||||||
|
writeBundle(_options, bundle) {
|
||||||
|
viteBundleFiles = Object.keys(bundle);
|
||||||
|
},
|
||||||
closeBundle() {
|
closeBundle() {
|
||||||
const outDir = path.join(__dirname, "static");
|
const outDir = path.join(__dirname, "static");
|
||||||
copyRootPublicFiles(resourcesDir, outDir);
|
copyRootPublicFiles(resourcesDir, outDir);
|
||||||
|
// Run the source→hashed copy first; createHashedPublicAssetFiles iterates
|
||||||
|
// assetManifest and expects every key to resolve to a file in resources/
|
||||||
|
// or proprietary/. Vite's bundle output (assets/...) doesn't, so it's
|
||||||
|
// merged in after.
|
||||||
createHashedPublicAssetFiles(sourceDirs, outDir, assetManifest);
|
createHashedPublicAssetFiles(sourceDirs, outDir, assetManifest);
|
||||||
|
// Track Vite's own bundle output (vendor chunks, JS, CSS, workers under
|
||||||
|
// static/assets/) in the manifest so the deploy-time R2 upload covers
|
||||||
|
// them alongside the hashed source assets. Skip non-assets/ emits like
|
||||||
|
// index.html — those are served by the app, not from R2.
|
||||||
|
for (const fileName of viteBundleFiles) {
|
||||||
|
if (!fileName.startsWith("assets/")) continue;
|
||||||
|
assetManifest[fileName] = `/${fileName}`;
|
||||||
|
}
|
||||||
writePublicAssetManifest(outDir, assetManifest);
|
writePublicAssetManifest(outDir, assetManifest);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user