perf(frontend): add build.rs asset pipeline with oxc + lightningcss
- Bundle 31 JS files → single app.{hash}.js (oxc minifier)
- Bundle 36 CSS files → single app.{hash}.css (lightningcss)
- Resolve CSS @import chains at build time
- Inline theme-init.js to eliminate render-blocking script
- Minify all individual JS/CSS/JSON assets in static-dist/
- Auto-update Service Worker cache manifest with bundle hashes
- FNV hash-based cache-busting filenames
Results: 88 → 12 requests, 640 kB → 96.5 kB transferred (-85%)
Build modes:
- Debug: copies HTML to OUT_DIR, serves original static/
- Release: generates static-dist/ with processed assets
Also:
- Update Dockerfile to include build.rs in cacher stage
- Serve static-dist/ in release Docker builds
- Remove host static/ bind mount from docker-compose
- Switch include_str!() to OUT_DIR for all HTML pages
This commit is contained in:
@@ -11,13 +11,25 @@ use tower_http::set_header::SetResponseHeaderLayer;
|
||||
pub fn create_web_routes() -> Router<Arc<AppState>> {
|
||||
// Get config to access static path
|
||||
let config = AppConfig::from_env();
|
||||
let static_path = config.static_path.clone();
|
||||
|
||||
// In release builds, serve from static-dist/ (processed assets).
|
||||
// In debug builds, serve from the original static/ directory.
|
||||
let static_path = if cfg!(not(debug_assertions)) {
|
||||
let dist = config
|
||||
.static_path
|
||||
.parent()
|
||||
.unwrap_or(std::path::Path::new("."))
|
||||
.join("static-dist");
|
||||
if dist.exists() { dist } else { config.static_path.clone() }
|
||||
} else {
|
||||
config.static_path.clone()
|
||||
};
|
||||
|
||||
// Static assets (JS, CSS, JSON, SVG, ICO) served via ServeDir
|
||||
// with brotli + gzip compression and aggressive caching (7 days).
|
||||
// HTML pages are served via explicit routes (include_str!) and
|
||||
// do NOT pass through these layers.
|
||||
let static_service = ServeDir::new(static_path);
|
||||
let static_service = ServeDir::new(&static_path);
|
||||
|
||||
Router::new()
|
||||
// Add specific routes for clean URLs (without .html)
|
||||
@@ -36,20 +48,23 @@ pub fn create_web_routes() -> Router<Arc<AppState>> {
|
||||
|
||||
/// Serve the login page
|
||||
async fn serve_login_page() -> Html<&'static str> {
|
||||
Html(include_str!("../../../static/login.html"))
|
||||
Html(include_str!(concat!(env!("OUT_DIR"), "/login.html")))
|
||||
}
|
||||
|
||||
/// Serve the profile page
|
||||
async fn serve_profile_page() -> Html<&'static str> {
|
||||
Html(include_str!("../../../static/profile.html"))
|
||||
Html(include_str!(concat!(env!("OUT_DIR"), "/profile.html")))
|
||||
}
|
||||
|
||||
/// Serve the admin page
|
||||
async fn serve_admin_page() -> Html<&'static str> {
|
||||
Html(include_str!("../../../static/admin.html"))
|
||||
Html(include_str!(concat!(env!("OUT_DIR"), "/admin.html")))
|
||||
}
|
||||
|
||||
/// Serve the device verification page (RFC 8628 Device Authorization Grant)
|
||||
async fn serve_device_verify_page() -> Html<&'static str> {
|
||||
Html(include_str!("../../../static/device-verify.html"))
|
||||
Html(include_str!(concat!(
|
||||
env!("OUT_DIR"),
|
||||
"/device-verify.html"
|
||||
)))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user