162 lines
5.0 KiB
Bash
Executable File
162 lines
5.0 KiB
Bash
Executable File
#!/bin/bash
|
|
# release.sh - Build optimized WASM and serve with Caddy + Brotli compression
|
|
set -e
|
|
|
|
###############################################################################
|
|
# Freezone Portal Release Script
|
|
# - Builds the WASM app with trunk in release mode
|
|
# - Optionally optimizes .wasm with wasm-opt (-Oz, strip)
|
|
# - Precompresses assets with gzip and brotli for efficient static serving
|
|
# - Generates a manifest (manifest.json) with sizes and SHA-256 checksums
|
|
#
|
|
# Usage:
|
|
# ./release.sh [--outdir dist] [--no-opt] [--compress] [--no-manifest]
|
|
# [--trunk-args "--public-url /portal/"]
|
|
#
|
|
# Notes:
|
|
# - Precompression is OFF by default; enable with --compress
|
|
# - Only modifies files within the output directory (default: dist)
|
|
# - Non-destructive to your source tree
|
|
###############################################################################
|
|
|
|
set -u
|
|
|
|
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
PROJECT_DIR=$(cd "$SCRIPT_DIR/.." && pwd)
|
|
BUILD_SCRIPT="$SCRIPT_DIR/build.sh"
|
|
|
|
# Defaults
|
|
OUTDIR="dist"
|
|
DO_OPT=1
|
|
DO_COMPRESS=0
|
|
DO_MANIFEST=1
|
|
TRUNK_ARGS=""
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
Usage: $(basename "$0") [options]
|
|
|
|
Options:
|
|
--outdir <dir> Output directory (default: dist)
|
|
--no-opt Skip wasm-opt optimization
|
|
--compress Enable gzip/brotli precompression
|
|
--no-manifest Skip manifest generation
|
|
--trunk-args "..." Extra arguments forwarded to trunk build
|
|
-h, --help Show this help
|
|
|
|
Examples:
|
|
$(basename "$0") --outdir dist --trunk-args "--public-url /"
|
|
$(basename "$0") --no-opt --no-compress
|
|
EOF
|
|
}
|
|
|
|
# Parse args
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--outdir)
|
|
OUTDIR="$2"; shift 2;;
|
|
--no-opt)
|
|
DO_OPT=0; shift;;
|
|
--compress)
|
|
DO_COMPRESS=1; shift;;
|
|
--no-manifest)
|
|
DO_MANIFEST=0; shift;;
|
|
--trunk-args)
|
|
TRUNK_ARGS="$2"; shift 2;;
|
|
-h|--help)
|
|
usage; exit 0;;
|
|
*)
|
|
echo "❌ Unknown option: $1"; echo; usage; exit 1;;
|
|
esac
|
|
done
|
|
|
|
# Tool checks
|
|
if [[ ! -x "$BUILD_SCRIPT" ]]; then
|
|
echo "❌ build.sh not found or not executable at: $BUILD_SCRIPT"
|
|
echo " Ensure portal/scripts/build.sh exists and is chmod +x."
|
|
exit 1
|
|
fi
|
|
if ! command -v trunk >/dev/null 2>&1; then
|
|
echo "❌ trunk not found. Install with: cargo install trunk"; exit 1;
|
|
fi
|
|
|
|
HAS_WASM_OPT=0
|
|
if command -v wasm-opt >/dev/null 2>&1; then HAS_WASM_OPT=1; fi
|
|
if [[ $DO_OPT -eq 1 && $HAS_WASM_OPT -eq 0 ]]; then
|
|
echo "⚠️ wasm-opt not found. Skipping WASM optimization."
|
|
DO_OPT=0
|
|
fi
|
|
|
|
if [[ $DO_COMPRESS -eq 1 ]]; then
|
|
if ! command -v gzip >/dev/null 2>&1; then
|
|
echo "⚠️ gzip not found. Skipping gzip compression."; GZIP_OK=0; else GZIP_OK=1; fi
|
|
if ! command -v brotli >/dev/null 2>&1; then
|
|
echo "⚠️ brotli not found. Skipping brotli compression."; BR_OK=0; else BR_OK=1; fi
|
|
else
|
|
GZIP_OK=0; BR_OK=0
|
|
fi
|
|
|
|
echo "🔧 Building optimized WASM bundle (via build.sh)..."
|
|
set -x
|
|
"$BUILD_SCRIPT" --release --outdir "$OUTDIR" ${TRUNK_ARGS:+--trunk-args "$TRUNK_ARGS"}
|
|
set +x
|
|
|
|
DIST_DIR="$PROJECT_DIR/$OUTDIR"
|
|
if [[ ! -d "$DIST_DIR" ]]; then
|
|
echo "❌ Build failed: output directory not found: $DIST_DIR"; exit 1;
|
|
fi
|
|
|
|
# Optimize .wasm files
|
|
if [[ $DO_OPT -eq 1 && $HAS_WASM_OPT -eq 1 ]]; then
|
|
echo "🛠️ Optimizing WASM with wasm-opt (-Oz, strip)..."
|
|
while IFS= read -r -d '' wasm; do
|
|
echo " • $(basename "$wasm")"
|
|
tmp="$wasm.opt"
|
|
wasm-opt -Oz --strip-dwarf "$wasm" -o "$tmp"
|
|
mv "$tmp" "$wasm"
|
|
done < <(find "$DIST_DIR" -type f -name "*.wasm" -print0)
|
|
fi
|
|
|
|
# Precompress assets
|
|
if [[ $DO_COMPRESS -eq 1 ]]; then
|
|
echo "🗜️ Precompressing assets (gzip/brotli)..."
|
|
while IFS= read -r -d '' f; do
|
|
if [[ $GZIP_OK -eq 1 ]]; then
|
|
gzip -kf9 "$f"
|
|
fi
|
|
if [[ $BR_OK -eq 1 ]]; then
|
|
brotli -f -q 11 "$f"
|
|
fi
|
|
done < <(find "$DIST_DIR" -type f \( -name "*.wasm" -o -name "*.js" -o -name "*.css" \) -print0)
|
|
fi
|
|
|
|
# Manifest with sizes and SHA-256
|
|
if [[ $DO_MANIFEST -eq 1 ]]; then
|
|
echo "🧾 Generating manifest.json (sizes, sha256)..."
|
|
manifest="$DIST_DIR/manifest.json"
|
|
echo "{" > "$manifest"
|
|
first=1
|
|
while IFS= read -r -d '' f; do
|
|
rel="${f#"$DIST_DIR/"}"
|
|
size=$(stat -f%z "$f" 2>/dev/null || stat -c%s "$f")
|
|
if command -v shasum >/dev/null 2>&1; then
|
|
hash=$(shasum -a 256 "$f" | awk '{print $1}')
|
|
else
|
|
hash=$(openssl dgst -sha256 -r "$f" | awk '{print $1}')
|
|
fi
|
|
[[ $first -eq 1 ]] || echo "," >> "$manifest"
|
|
first=0
|
|
printf " \"%s\": { \"bytes\": %s, \"sha256\": \"%s\" }" "$rel" "$size" "$hash" >> "$manifest"
|
|
done < <(find "$DIST_DIR" -type f ! -name "manifest.json" -print0 | sort -z)
|
|
echo "\n}" >> "$manifest"
|
|
fi
|
|
|
|
echo "📦 Checking bundle sizes ($OUTDIR)..."
|
|
if [ -d "$OUTDIR" ]; then
|
|
echo "Bundle sizes:"
|
|
find "$OUTDIR" -name "*.wasm" -exec ls -lh {} \; | awk '{print " WASM: " $5 " - " $9}'
|
|
find "$OUTDIR" -name "*.js" -exec ls -lh {} \; | awk '{print " JS: " $5 " - " $9}'
|
|
find "$OUTDIR" -name "*.css" -exec ls -lh {} \; | awk '{print " CSS: " $5 " - " $9}'
|
|
echo ""
|
|
fi
|