litespeedtech / litespeedtech/lscache_wp
guest_optm=1 silently overrides optm-js_defer=0 at runtime, breaking mobile navigation on Kadence themes
- Dominant language
- PHP
- Stars
- 257
- Forks
- 123
- PR merge metrics
- No merged PRs in 30d
Description
## Bug summary
When **Guest Optimization** (`guest_optm = 1`) is enabled, the plugin defines a PHP constant `LITESPEED_GUEST_OPTM` that **unconditionally forces JS defer mode 2 (delay) on all guest requests**, regardless of what the user has set for `optm-js_defer`. Setting `optm-js_defer = 0` via WP Admin or WP-CLI has no effect while `guest_optm = 1` is active.
This is a silent override with no indication in the UI, no warning, and no documentation. The individual setting reads back as `0` from the database, giving the administrator full confidence the feature is disabled — while the plugin ignores it at runtime.
---
## Root cause — exact source lines
**`vary.cls.php` line ~222:**
```php
if ( $this->conf( Base::O_GUEST_OPTM ) ) {
! defined( 'LITESPEED_GUEST_OPTM' ) && define( 'LITESPEED_GUEST_OPTM', true );
}
```
**`optimize.cls.php` lines ~84–88:**
```php
$this->cfg_js_defer = $this->conf(self::O_OPTM_JS_DEFER);
if (defined('LITESPEED_GUEST_OPTM')) {
$this->cfg_js_defer = 2; // ← unconditionally overrides the user's setting
}
```
**`optimize.cls.php` line ~290:**
```php
$this->cfg_js_comb = defined('LITESPEED_GUEST_OPTM') || $this->conf(self::O_OPTM_JS_COMB);
```
`LITESPEED_GUEST_OPTM` similarly force-enables `css_async`, `js_comb`, lazy load, VPI, and other features regardless of their individual settings.
---
## Reproduction steps
1. Enable Guest Optimization (`guest_optm = 1`) — the default on Hostinger-hosted WordPress installations.
2. Disable JS Defer via WP Admin (Page Optimization → JS Settings → JS Defer: OFF) or via WP-CLI: `wp option update litespeed.conf.optm-js_defer 0`
3. Confirm the option reads back as `0`: `wp option get litespeed.conf.optm-js_defer` → `0`
4. Visit any page as a logged-out user.
5. Observe: `type="litespeed/javascript"` is still applied to script tags. The delayed JS loader (`litespeed_load_delayed_js_force`) is still injected.
**Verification command:**
```bash
curl -s https://yoursite.com/ | grep -c 'litespeed_load_delayed_js'
# Returns > 0 even though optm-js_defer = 0
```
---
## Real-world impact
On a live production site (WordPress + Kadence theme + WooCommerce + Hostinger Cloud):
The Kadence navigation JS is bundled into a combined file where LiteSpeed rewrites `DOMContentLoaded` → `DOMContentLiteSpeedLoaded` (the custom event dispatched by the delay loader). The delay loader fires only on first user interaction. When the user's first interaction **is** clicking the mobile hamburger menu, the nav JS has not yet executed — the click is consumed by the loader trigger, and the menu does not open.
Result: **the mobile hamburger menu is non-functional on first interaction for all logged-out visitors**, across all page types that receive the bundled JS.
The administrator had correctly set `optm-js_defer = 0` to disable this feature. The plugin silently ignored that setting. The failure was only discovered by reading PHP source code — there is nothing in the UI, the option's own description, or `guest_optm`'s description that indicates this override behavior exists.
---
## Naming confusion compounds the problem
There are three option keys with nearly identical names and no clear relationship documented between them:
| DB key | Constant | What it actually does |
|--------|----------|-----------------------|
| `litespeed.conf.guest` | `O_CACHE_GUEST` | Enable page caching for guests |
| `litespeed.conf.guest_optm` | `O_GUEST_OPTM` | Force-enable ALL optimizations for guests, overriding individual flags |
| `litespeed.conf.optm-guest_only` | `O_OPTM_GUEST_ONLY` | Apply optimization only to guests (only relevant when individual flags are ON) |
An administrator disabling `optm-js_defer` has no reason to know that `guest_optm` makes that setting meaningless.
---
## Expected behavior
Setting `optm-js_defer = 0` should disable JS defer for all requests. If `guest_optm` is intended to override individual settings, this must be:
1. Clearly documented in the UI (e.g., a notice on the JS Defer setting: "Overridden by Guest Optimization")
2. Clearly documented in the plugin docs
3. Or removed — individual settings should be respected regardless of master switches
---
## Environment
- LiteSpeed Cache plugin: 7.8.1
- WordPress: current
- Theme: Kadence
- Host: Hostinger Cloud (LSWS) — `guest_optm = 1` appears to be the default on this platform
- PHP: 8.x
---
Note: Issue #975 describes a related visible symptom (unstyled content flash with Guest Optimization enabled) but does not identify the root cause or the silent override behavior documented here.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start in vary.cls.php around line 222 and optimize.cls.php around lines 84–88 and 290 to trace how LITESPEED_GUEST_OPTM changes the individual optimization settings. Reproduce the guest request with WP-CLI and curl, then inspect the related option descriptions and issue #975. Done means the guest request no longer silently contradicts the administrator’s optm-js_defer setting, with the intended override behavior made explicit.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- php, wordpress
- Domain
- backend, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100