# Performance

> How AndOr keeps storefront pages light, when its scripts load, and what works without JavaScript.

Source: https://backtrackhq.com/docs/developers/performance/

AndOr loads as little as it can on each page. Data is read in Liquid on
the server, scripts are deferred, and most files load only on pages that
use them.

## Files come from Shopify's CDN

AndOr's scripts and styles are part of a theme app extension, so Shopify
serves them from its own CDN, under `cdn.shopify.com/extensions/`. No
AndOr file loads from any other host, and there is nothing for you to
host.

## Data is read in Liquid

The widgets read the `$app:andor_display` metafields in Liquid, on the
server. A widget does not call an API to find its discount. The discount
is picked before the HTML reaches the shopper.

## Scripts are deferred

The app embed loads its script with `defer`, so it never blocks the page
from drawing. That script draws nothing itself. It brings in the other
scripts when the page needs them.

## Files load only where needed

The embed runs on every page, so it keeps its own part small. Other
scripts load only on pages that need them. For example, the volume tier
files load only on product pages with tiers, and the gift chooser loads
the first time a gift slot needs it.

Several blocks share one stylesheet, and Shopify loads it once per page.
So a page with four widgets still loads one stylesheet.

## One shared cart read

All AndOr scripts share one `/cart.js` read per cart change. While a cart
write is in flight (an add form submit, a lines update), every read waits
for it to land. After that, every script uses the same answer.

## What works without JavaScript

| Widget | With JavaScript off |
|---|---|
| Sale price | correct |
| Savings badge | correct |
| Volume table | correct |
| Collection banner and discount callout | correct |
| Product card recipes | correct (they use no JavaScript) |
| Goal bar | keeps its space and shows nothing |
| Countdown, offers list, volume picker, offer picker, claim rows | keep their space and show nothing |

The goal bar needs JavaScript. Without it the bar stays invisible rather
than showing a wrong amount.

## No layout shift on first paint

Widgets printed by JavaScript first print a skeleton at the finished
size, with the same elements and classes. The page does not move when
the words arrive. Keep it that way: change a widget's custom properties,
not its own `padding`, `height` or `font-size`. See
[Data attributes and states](https://backtrackhq.com/docs/developers/data-attributes/).

## Network calls

Every call goes to the store's own domain:

- `/cart.js` and `/cart/*.js`.
- `?sections=`, for Dawn's cart drawer redraw.
- Upsell offer counts, sent through your store's app proxy, only after
  the shopper's consent.
- Error reports from AndOr's own files, sent through your store's app
  proxy.
