Shopify CSS or JS Changes Not Showing? Fix the Cache

You edited a stylesheet, saved, hard-refreshed — and the live store still serves the old file.
This is one of the longest-running complaints in Shopify theme development. The file is updated in the admin, but the CDN keeps handing out the previous version. Here is what actually causes it and what still works in 2026.
Symptom
- A CSS or JS change is visible in the code editor but not on the storefront.
- A hard refresh and cache clear change nothing.
- The file looks correct when opened directly from the CDN URL — or sometimes does not.
.js.liquidand.css.liquidfiles are affected most often.- The theme editor preview shows the new version while the live store shows the old one.
Cause
1. The CDN caches aggressively, keyed on the URL
Shopify serves assets from its CDN with long cache lifetimes. The URL is the cache key, so if the URL does not change, cached copies stay valid — regardless of what you uploaded.
The asset_url filter normally handles this by appending a version fingerprint. Problems start when that fingerprint does not update.
2. A .js.liquid file referencing other assets does not re-fingerprint
This is the specific long-standing bug. A .js.liquid file that references another asset via asset_url does not get a new fingerprint when that referenced asset changes. The outer file's own content is unchanged, so Shopify sees no reason to bump its version — and serves the stale build.
3. Bare query strings stopped working in March 2026
This is the one that breaks old workarounds. As of 24 March 2026, a bare query string — a ? followed by a value with no key — no longer busts the asset cache.
{%- comment -%} No longer busts the cache as of 2026-03-24 {%- endcomment -%}
<link rel="stylesheet" href="{{ 'custom.css' | asset_url }}?{{ 'now' | date: '%s' }}">
{%- comment -%} Use a proper key=value parameter instead {%- endcomment -%}
<link rel="stylesheet" href="{{ 'custom.css' | asset_url }}&v={{ 'now' | date: '%s' }}">
If cache busting worked for you last year and silently stopped, this change is almost certainly why.
Fix
1. Always use asset_url and its filters
{%- comment -%} Correct — Shopify adds a content fingerprint {%- endcomment -%}
{{ 'theme.css' | asset_url | stylesheet_tag }}
{{ 'theme.js' | asset_url | script_tag }}
{%- comment -%} Wrong — hard-coded path, no fingerprint, cached forever {%- endcomment -%}
<link rel="stylesheet" href="/assets/theme.css">
If you are already using asset_url, you are compatible with Shopify's cache-busting improvements and most problems disappear.
2. For the .js.liquid bug, force a version bump
Since the outer file only re-fingerprints when its own content changes, change its content — deliberately and traceably:
{%- comment -%}
assets/bundle.js.liquid
Bump ASSET_VERSION whenever a referenced asset changes, so the CDN
fingerprint for this file changes too. Shopify does not do this for us.
{%- endcomment -%}
{%- assign ASSET_VERSION = '2026-09-28-1' -%}
/* build: {{ ASSET_VERSION }} */
var CONFIG_URL = "{{ 'config.json' | asset_url }}";
The comment is a single line of output, and changing it guarantees a new fingerprint.
3. Prefer plain assets over .liquid assets
The cleanest fix is to avoid the bug entirely. Most .js.liquid files exist only to inject a couple of Liquid values. Pass those through a data attribute instead and keep the JavaScript a plain, cacheable static file:
{%- comment -%} layout/theme.liquid {%- endcomment -%}
<script
src="{{ 'theme.js' | asset_url }}"
data-cart-url="{{ routes.cart_url }}"
data-money-format="{{ shop.money_format | escape }}"
defer
></script>
// assets/theme.js — a plain asset, correctly fingerprinted, better cached.
const el = document.currentScript;
const CART_URL = el.dataset.cartUrl;
const MONEY_FORMAT = el.dataset.moneyFormat;
This also improves performance: a static .js file is cached far more effectively than one rendered per request.
4. When you need an immediate flush
Renaming the file guarantees a new URL and therefore a cache miss:
assets/custom.css → assets/custom-v2.css
Update the reference, deploy, confirm. It is blunt, but it always works — useful when a fix is live and something is still stale.
Verify
Check what the CDN is actually serving, rather than trusting the browser:
# Fingerprint should change after a deploy.
curl -sI "https://yourstore.com/cdn/shop/t/1/assets/theme.css" | grep -i "etag\|cache-control\|last-modified"
Then:
- Load the storefront in a private window — no extensions, no service worker.
- DevTools → Network → tick "Disable cache" → reload → confirm the asset URL carries a new version parameter.
- Compare the served file against your local copy.
Prevent
- Never hard-code
/assets/paths. Always go throughasset_url. - Keep JavaScript in plain
.jsfiles, passing Liquid values via data attributes. - Use
key=valuequery parameters, never bare ones — they stopped working in March 2026. - Version deliberately. A build constant you bump is more reliable than hoping Shopify notices.
Frequently asked questions
Why does it work in the theme editor but not live?
The editor bypasses much of the CDN cache to show your work immediately. The live storefront does not. Always verify on the real URL.
How long until the cache expires on its own?
Long enough that waiting is not a strategy. Change the URL rather than waiting it out.
Does this affect section {% stylesheet %} and {% javascript %} tags?
Those are bundled into theme-level assets and have had their own caching quirks reported. If a section asset seems stuck, move the code into a normal asset file referenced with asset_url.
Related reading
- Liquid error: unknown tag "schema"
- Fixing layout shift on collection pages
- Shopify theme development — our service page
Need a hand?
We build and maintain Shopify themes for merchants in the USA, UAE, Saudi Arabia, Qatar and the UK. If deploys are not showing up, get a free audit or see our Shopify theme development work.
The Yaxify Team
Shopify & Web Development Agency
We build custom Shopify stores and high-performance websites for growing businesses across the USA, UK, and UAE. Everything we publish comes out of client work we have actually shipped.
More about Yaxify →