3.3 KiB
3.3 KiB
XShop – Performance
1. Budgets
- LCP < 2.5s on mid-tier mobile (4G, Moto G4 class).
- Total blocking JS < 150ms.
- No render-blocking webfont swap beyond FOIT 100ms (use
font-display: swap). - DB queries: shop archive < 12 queries, product < 15 (WC baseline excluded).
2. Assets
- Conditional enqueue: each module (
search,filter,gallery,wishlist) enqueued only where needed (is_shop,is_product,is_search, or presence of shortcode/block). - No global JS: single
xshop.jsis ~5KB bootstrap; feature modules lazy-imported viaimport(). - CSS: tokens + base always; component CSS split but concatenated in release (critical inline optional, not required v1).
- No jQuery for new code; WC jQuery remains for its own handlers.
- Images:
loading="lazy"+decoding="async"+srcset, hero eager. Thumbnails viawp_get_attachment_image. - Fonts: system stack default; optional Vazirmatn self-hosted, subset, no external request by default.
3. Queries
- Avoid N+1: prime post caches (
update_post_meta_cache,update_post_term_cache), usewc_get_productswithreturn => idswhere only IDs needed, thenwc_get_productin loop. - Cache expensive counts: filter counts via transient (5 min), search suggestions via transient (5 min).
- No queries on
initfor frontend; defer to template.
4. Caching
- Transients for search/filter counts;
wp_cachefor in-request repeated lookups (e.g.,xshop_get_setting). - Compatibility with WP Rocket / LiteSpeed – no
DONOTCACHEPAGEabuse.
5. Minification
- Release build minifies CSS/JS (
tools/build-release.ps1runs cssnano/terser or PHP minify). Source maps for dev.
6. DOM
- Minimal wrappers, no deep nesting. No layout thrash (batch DOM reads/writes).
- Carousel: CSS scroll-snap, no heavy JS.
7. Monitoring
System Statusreports: PHP/WP/WC versions, active plugins, asset sizes, transient hit rate.- Lighthouse CI optional (not required for v1).
8. Search Performance (M3)
- Debounce: 250ms in
assets/js/search.js:debounce(200–300ms target). Prevents request on every keystroke. - Min length: 2 chars (handler returns empty without query). Input
data-min-length. - Bounded:
limitdefault 6, max 20, validated; handler over-fetcheslimit*2for dedup then slices tolimit; max 40 IDs scanned. - Stale protection:
AbortControllercancels previous fetch + monotonicseqcounter ignores stale JSON; rapidiph → iphonecannot overwrite newer. - Dedupe: identical query (
lastQuery) reopens dropdown without fetch. - Query:
WP_Querys+_skuLIKE,post_status publish,no_found_rows,fields ids, no N+1,wc_get_productonly for returned IDs (≤6). - Asset:
search.jsenqueued only on front-end wheredata-xshop-searchexists (header on all front-end pages, guarded viainitAll);woo.cssglobal intentional. - Caching: server
Cache-Control: public, max-age=60; no client cache beyond in-memorylastQuery(no stale invalidation issues). - Payload: minimal 6 items × 6 fields (~2KB JSON).
9. Anti-Patterns Forbidden
- Global
wp_enqueue_scriptwithout condition. - Querying all products to compute filters.
- Unbounded
WP_Querywithoutposts_per_page/no_found_rows. - External fonts/CDNs by default.