From 576922160ea1491b786df091ff4d13d2597a58f6 Mon Sep 17 00:00:00 2001 From: magdev Date: Thu, 19 Feb 2026 18:26:40 +0100 Subject: [PATCH] perf: color variation CSS transient caching and Twig auto_reload fix (v1.0.9) - functions.php: cache wp_bootstrap_variation_colors() output in a 24-hour transient keyed by md5(get_stylesheet()); invalidate on switch_theme and save_post_wp_global_styles so Design Editor changes apply immediately - TwigService.php: change auto_reload from hardcoded true to WP_DEBUG so Twig stops stat()-ing compiled template files on every production request Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 7 +++++++ CLAUDE.md | 18 +++++++++++++++++- functions.php | 26 ++++++++++++++++++++++++++ inc/Twig/TwigService.php | 6 +++--- style.css | 2 +- 5 files changed, 54 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50a9a2b..e3c5af8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. +## [1.0.9] - 2026-02-19 + +### Performance + +- **Color variation CSS transient caching** (`functions.php`): `wp_bootstrap_variation_colors()` now caches the generated inline CSS in a 24-hour WordPress transient keyed by `wp_bootstrap_variation_css_` + an MD5 of the active stylesheet slug. Previously the palette iteration and CSS string building ran on every frontend page load. The transient is immediately invalidated on `switch_theme` and `save_post_wp_global_styles`, so changes made via the Design Editor are reflected instantly. +- **Twig template recompilation gated behind `WP_DEBUG`** (`inc/Twig/TwigService.php`): `auto_reload` in the Twig `Environment` constructor was hardcoded to `true`, causing Twig to stat every compiled template file on every request to check for source changes. Changed to `WP_DEBUG` so template recompilation only occurs during development. In production (`WP_DEBUG = false`) compiled Twig templates are served from cache without filesystem mtime checks. + ## [1.0.8] - 2026-02-19 ### Security diff --git a/CLAUDE.md b/CLAUDE.md index 0c8a0fe..35decb8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -34,7 +34,7 @@ This project is proudly **"vibe-coded"** using Claude.AI - the entire codebase w **Note for AI Assistants:** Clean this section after the specific features are done or new releases are made. Effective changes are tracked in `CHANGELOG.md`. Do not add completed versions here - document them in the Session History section at the end of this file. -Current version is **v1.0.5**. See `PLAN.md` for details. +Current version is **v1.0.9**. See `PLAN.md` for details. ## Technical Stack @@ -211,6 +211,22 @@ Build steps (in order): ## Session History +### Session 15 — v1.0.9 Performance Optimization (2026-02-19) + +**Completed:** Two targeted performance fixes for production environments. + +**Changes made:** + +- **Color variation CSS transient caching** (`functions.php`): `wp_bootstrap_variation_colors()` now caches the generated Bootstrap CSS variable overrides in a 24-hour transient keyed by `wp_bootstrap_variation_css_` + `md5(get_stylesheet())`. Previously the palette loop and CSS string building executed on every frontend request. Transient is invalidated on `switch_theme` and `save_post_wp_global_styles` hooks so Design Editor changes apply immediately. +- **Twig `auto_reload` gated behind `WP_DEBUG`** (`inc/Twig/TwigService.php`): Hardcoded `auto_reload => true` caused Twig to `stat()` each compiled template file on every request to detect source file changes. Changed to `auto_reload => WP_DEBUG` so stat checks only occur during development. In production, compiled templates are served from cache unconditionally. + +**Files modified:** + +- `functions.php` — transient caching and invalidation for variation CSS +- `inc/Twig/TwigService.php` — `auto_reload => WP_DEBUG` +- `style.css` — version bump to 1.0.9 +- `CHANGELOG.md` — v1.0.9 entry + ### Session 14 — v1.0.8 Security Audit & Hardening (2026-02-19) **Completed:** Comprehensive OWASP-aligned security audit. Two parallel background agents reviewed all PHP (functions.php, ContextBuilder, NavWalker, TemplateController, TwigService, all patterns) and JavaScript/Twig templates. Four targeted security fixes applied. diff --git a/functions.php b/functions.php index 03834c3..3b80906 100644 --- a/functions.php +++ b/functions.php @@ -175,6 +175,17 @@ add_action( 'wp_enqueue_scripts', 'wp_bootstrap_rtl_styles', 20 ); */ if ( ! function_exists( 'wp_bootstrap_variation_colors' ) ) : function wp_bootstrap_variation_colors() { + $transient_key = 'wp_bootstrap_variation_css_' . md5( get_stylesheet() ); + $cached_css = get_transient( $transient_key ); + + if ( false !== $cached_css ) { + // '' means default palette (no inline CSS needed); non-empty string is the computed CSS. + if ( '' !== $cached_css ) { + wp_add_inline_style( 'wp-bootstrap-style', $cached_css ); + } + return; + } + // Read the theme origin palette — this contains the base theme.json // colors merged with the active style variation (if any). $theme_palette = wp_get_global_settings( array( 'color', 'palette', 'theme' ) ); @@ -205,10 +216,12 @@ if ( ! function_exists( 'wp_bootstrap_variation_colors' ) ) : // No variation active — let Bootstrap's compiled CSS handle both modes. if ( $is_default ) { + set_transient( $transient_key, '', DAY_IN_SECONDS ); return; } if ( empty( $colors['base'] ) || empty( $colors['contrast'] ) ) { + set_transient( $transient_key, '', DAY_IN_SECONDS ); return; } @@ -280,6 +293,9 @@ if ( ! function_exists( 'wp_bootstrap_variation_colors' ) ) : . '[data-bs-theme=light]{' . $light_css . '}' . '[data-bs-theme=dark]{' . $dark_css . '}'; + // Cache for 24 hours; invalidated on theme switch or global-styles save. + set_transient( $transient_key, $css, DAY_IN_SECONDS ); + // Attach after the compiled stylesheet so variation values override // Bootstrap's hardcoded dark-mode defaults via source order. wp_add_inline_style( 'wp-bootstrap-style', $css ); @@ -287,6 +303,16 @@ if ( ! function_exists( 'wp_bootstrap_variation_colors' ) ) : endif; add_action( 'wp_enqueue_scripts', 'wp_bootstrap_variation_colors', 30 ); +/** + * Invalidate the color variation CSS transient when global styles or theme change. + */ +add_action( 'switch_theme', function () { + delete_transient( 'wp_bootstrap_variation_css_' . md5( get_stylesheet() ) ); +} ); +add_action( 'save_post_wp_global_styles', function () { + delete_transient( 'wp_bootstrap_variation_css_' . md5( get_stylesheet() ) ); +} ); + /** * Build Bootstrap surface CSS variables for a given background/foreground pair. * diff --git a/inc/Twig/TwigService.php b/inc/Twig/TwigService.php index 194e19a..f4a81eb 100644 --- a/inc/Twig/TwigService.php +++ b/inc/Twig/TwigService.php @@ -25,9 +25,9 @@ class TwigService $loader = new FilesystemLoader($viewsDir); $this->twig = new Environment($loader, [ - 'cache' => WP_DEBUG ? false : $cacheDir, - 'debug' => WP_DEBUG, - 'auto_reload' => true, + 'cache' => WP_DEBUG ? false : $cacheDir, + 'debug' => WP_DEBUG, + 'auto_reload' => WP_DEBUG, ]); $this->registerWordPressFunctions(); diff --git a/style.css b/style.css index 8dafad9..721fa1e 100644 --- a/style.css +++ b/style.css @@ -7,7 +7,7 @@ Description: A modern WordPress Block Theme built from scratch with Bootstrap 5. Requires at least: 6.7 Tested up to: 6.7 Requires PHP: 8.3 -Version: 1.0.8 +Version: 1.0.9 License: GNU General Public License v2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html Text Domain: wp-bootstrap