---
title: Serve assets from Shopify CDN
description: >-
  Serve all theme assets through the Shopify CDN by placing them in the
  `/assets` folder and referencing them with `asset_url` to eliminate extra DNS
  connections for each external domain.
source_url:
  html: >-
    https://shopify.dev/docs/storefronts/themes/best-practices/performance/use-shopify-cdn
  md: >-
    https://shopify.dev/docs/storefronts/themes/best-practices/performance/use-shopify-cdn.md
api_name: liquid
---

# Serve assets from Shopify CDN

Serve all theme assets from the Shopify CDN instead of external domains to eliminate connection overhead for each domain.

***

## Why

Shopify serves theme assets, such as CSS, JavaScript, fonts, and images, through its CDN. Asset URLs are [moving from the shared `cdn.shopify.com` domain to your store's own domain](https://changelog.shopify.com/posts/changes-to-asset-urls) under a `/cdn` path, for example `/cdn/shop/files/hero.jpg`. When an asset is served from the store domain, it's same-origin with the HTML document, so the browser reuses the connection it already has: no extra DNS lookup, TCP connection, or TLS handshake.

The migration is still rolling out, so some requests still use `cdn.shopify.com`. Theme editor previews, some Shopify platform assets, and some regions continue to use the shared domain, and Shopify's font library is served from `fonts.shopifycdn.com` when store-domain URLs aren't in use. You don't control which URL is emitted: the platform picks it at render time. What you control is whether the asset goes through Shopify at all.

Connection overhead per external domain includes the DNS lookup, TCP connection, and TLS handshake, all before the first byte of the asset downloads. Multiple domains compound this problem.

***

## How

Move assets to the theme's `assets/` directory and reference them with the [`asset_url`](https://shopify.dev/docs/api/liquid/filters/asset_url) Liquid filter:

### Before

```html
<link rel="stylesheet" href="https://external-domain.com/style.css" />
<script src="https://external-domain.com/script.js"></script>
<img src="https://external-domain.com/image.jpg" alt="..." />
```

### After

```liquid
<link rel="stylesheet" href="{{ 'style.css' | asset_url }}">
<script src="{{ 'script.js' | asset_url }}"></script>
<img src="{{ 'image.jpg' | asset_url }}" alt="...">
```

### Automatic asset versioning

The `asset_url` filter appends version numbers to URLs. When you update a file, the version number changes, forcing browsers to download the new version.

```liquid
{{ 'style.css' | asset_url }}
{%- comment -%} Outputs: /cdn/.../style.css?v=1384022871 {%- endcomment -%}
```

Without versioning, browsers might cache outdated assets for days.

### CSS background images

For images referenced in CSS, use `asset_url` in a `.css.liquid` file:

## assets/style.css.liquid

```liquid
.hero {
  background: url({{ 'bg.jpg' | asset_url }});
}
```

The source file must have a `.css.liquid` extension for Shopify to process the Liquid code inside it. Reference it as `style.css`, without the `.liquid` extension: Shopify serves the compiled asset under that name.

***

## Examples

Target: minimize external domains. Aim for a maximum of one external domain beyond your store domain. Theme assets served through `asset_url` add little or no connection overhead, because they're served either from the same origin as your HTML or from a Shopify domain the browser is already connected to.

When you can't use the Shopify CDN, such as when third-party services don't allow copying files or require dynamic updates, check the service's documentation. If you must use an external domain, then add a `preconnect` hint to warm up the connection early.

***

## Testing

* [Chrome DevTools Network panel](https://developer.chrome.com/docs/devtools/network): count unique domains and measure connection overhead.
* **Network** tab: verify that assets load from your store domain or a Shopify domain rather than from third-party domains.
* Compare before and after: total connection time with and without external domains.

***

## References

* [`asset_url`](https://shopify.dev/docs/api/liquid/filters/asset_url) filter
* [Using the Shopify CDN for better performance](https://performance.shopify.com/blogs/blog/using-shopify-cdn-for-better-performance)
* [The Shopify platform: CDN](https://shopify.dev/docs/storefronts/themes/best-practices/performance/platform#shopify-cdn)
* [Self-host web fonts on Shopify CDN](https://shopify.dev/docs/storefronts/themes/best-practices/performance/self-host-web-fonts)
* [Avoid request proxies](https://shopify.dev/docs/storefronts/themes/best-practices/performance/avoid-request-proxies)

***
