SDWSKi Cache. Caching plugin for WordPress
the project
Page caching plugin for WordPress with e-commerce support. SDWSKi Cache serves ready-made HTML pages before WordPress even loads, stores them pre-compressed, and carefully bypasses the cache wherever the page depends on the specific visitor: shopping cart, account, comments, and private posts.
This project is a GPL-licensed page caching plugin built around the standard caching rules in WordPress: the core caching principles have been retained, while the serving engine, WooCommerce mode, interface, and conflict protection have been written entirely from scratch.
The Challenge
Standard caching plugins work well for blogs but poorly for online stores. Here are the common issues I wanted to address:
- a page showing another visitor's cart count gets cached;
- the product page continues to show an outdated stock level;
- a multilingual site serves visitors a page in the wrong language;
- if optimization fails (minification or file merging), the user sees a blank screen;
- the admin area is full of ads and links to third-party websites.
Architecture
The plugin consists of three layers, each handling its own part of the task.
1. Loader (sdwski-cache.php). It does just one thing: determines whether the engine can be started. If the original plugin or another copy is already active on the site, the loader does not load anything or register any hooks, and displays a notice with a “Deactivate and Launch” button. All engine classes, functions, and constants have their own prefixes, so “Cannot redeclare” errors are prevented regardless of the order in which WordPress loads the plugins.
2. Engine (sdwski-engine.php, inc/). The classic layer: cache generation and purging, CSS/JS minification and concatenation, preloading, exclusion rules, CDN (including Cloudflare), Varnish purging, a security module, a purge scheduler, and WP-CLI. Page output is also captured here via an output buffer.
3. Turbo layer (inc/turbo/). My main contribution. This is a drop-in advanced-cache.php, which WordPress loads before the theme and plugins, and a core turbo-core.php, which manages its settings, status, and purging.
How serving from the drop-in works
The order of checks in advanced-cache.php is structured so that whenever there is any doubt, the request is passed to WordPress:
- Only requests are processed
GET. - Preload bot requests are always passed to WordPress so that the page can be created or updated.
- The host and scheme (http/https) must match the site URL, covering variants with
wwwand without it. - If the cookies indicate a logged-in user, commenter, password-protected post, or store session, the visitor receives the live page. You can extend the list with your own cookie names.
- Only then is the cache checked for a ready-made file.
If the file is found, the response is assembled without starting WordPress. The headers include Vary: Accept-Encoding, ETag and X-ruzi-Turbo: HIT, which can be conveniently checked in the browser or via curl -I.
Precompressed copies and conditional requests
Compression is performed once when the page is created, rather than on every request. Next to index.html are stored index.html.gz and, if the server has the Brotli extension, index.html.br. The drop-in checks the header Accept-Encoding and serves the appropriate variant. For a conditional request with a matching ETag responds 304 without reading the file.
When the cache is cleared, all versions of the page are deleted: regular, gzip, and Brotli, as well as paginated pages and language-specific copies. This prevents “orphaned” compressed files that would otherwise outlive the deleted page.
Online store mode (WooCommerce)
The most extensive part of the work. The rules are duplicated at three levels: in .htaccess, in the drop-in, and in the engine, so protection does not depend on a single switch.
| The Challenge | Solution |
|---|---|
| Someone else's cart in the cache | A visitor with items in their cart or an active store session always receives a live page, and their request does not populate the shared cache |
| Cart, checkout, account | These pages are never cached |
| Outdated stock and price | Changes to a product, stock, price, status, or order clear the cache. Default mode: the entire cache. Hooks are used woocommerce_update_product, woocommerce_order_status_changed and transition_post_status |
| Imports bypassing WooCommerce | Maximum cache age, 3 hours by default |
| Cart counter in the header | The cached value is always zero; the actual number is inserted by a small script using the specified CSS class. On the server, formats such as “(3)” and “3 items” are also recognized when resetting the value to zero. |
| Stock level on the product card | The stock status string is fetched again every time a product or catalog page is viewed |
| Mini-cart | The entire block is updated via WooCommerce fragments |
| Prices based on currency or group | Optional “no-cache” mode for such pages |
All store settings are located on a separate “WooCommerce” tab. Element classes can be entered without a leading dot, for example cart-count.
Многоязычность
The cache is maintained separately for each language, so a visitor using the English version will not receive the Russian cache and vice versa. The plugin SDWSKi Cache совместим с плагинами мультиязычности. В первую очередь 100% гарантирована совместимость с плагином ИИ-перевода SDWSKi Translate.
Fault tolerance
- Rollback if optimization fails. The callback output buffer is protected: if file minification or merging fails, the original page is served.
- The drop-in can be removed at any time. WordPress then simply continues to work as usual, as stated in the file header itself.
- The Turbo status page shows, item by item, whether everything is configured correctly: the drop-in, permissions,
.htaccess, and brotli availability. - Safe removal. The plugin does not remove shared data as long as another copy of the engine remains on the site.
What else is included
Scheduled cache preloading via WP-Cron, HTML/CSS/JS minification, file combining, image lazy loading, exclusion rules, cache clearing for specific pages, Nginx and Varnish settings, CDN integrations, browser caching, emoji disabling, and WP-CLI. The interface and the detailed “Instructions” tab have been translated into Russian.
Stack
PHP, WordPress Plugin API (hooks, WP-Cron, output buffering, drop-in advanced-cache.php), Apache rules .htaccess, JavaScript and CSS for the admin interface and dynamic storefront elements, gettext (.pot, .po, .mo) for localization.
Installation
- Copy the folder
sdwski-cachein/wp-content/plugins/and activate the plugin. - In the “SDWSKi Cache” menu, enable “Cache System” and save your changes.
- Go to “Settings → SDWSKi Cache: Turbo” and make sure all status indicators are green.
- Check the result: open the page in a private window and locate the header
X-ruzi-Turbo: HIT.
История версий
- 1.5.3-turbo.10 — a separate WooCommerce tab, “live” stock, “live” mini-cart.
- 1.5.3-turbo.9 — cart and stock protection is now always enabled when WooCommerce is active, the cache is cleared whenever a product or order is changed, and the maximum cache age is 3 hours.
- 1.5.3-turbo.8 — the cart counter is inserted by a script; saving store mode settings has been fixed.
- 1.5.3-turbo.2 — protection against conflicts with the original plugin, a dedicated folder, and an “Instructions” tab.
- 1.5.3-turbo.1 — store mode, drop-in, pre-compressed pages, ETag and 304, a new interface, and ads removed.
License and Origin
This project is distributed under GPLv2 or later. It is based on an open-source GPL page caching plugin: the source code belongs to its authors, while my changes and additions are provided separately and described above.