Skip to content

Commit 064bfb2

Browse files
committed
Add performance measurement to Cart AJAX
1 parent bbfd08b commit 064bfb2

File tree

3 files changed

+96
-51
lines changed

3 files changed

+96
-51
lines changed

assets/cart.js

+56-49
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ class CartRemoveButton extends HTMLElement {
55
this.addEventListener('click', (event) => {
66
event.preventDefault();
77
const cartItems = this.closest('cart-items') || this.closest('cart-drawer-items');
8-
cartItems.updateQuantity(this.dataset.index, 0);
8+
cartItems.updateQuantity(this.dataset.index, 0, event);
99
});
1010
}
1111
}
@@ -76,6 +76,7 @@ class CartItems extends HTMLElement {
7676
this.updateQuantity(
7777
index,
7878
inputValue,
79+
event,
7980
document.activeElement.getAttribute('name'),
8081
event.target.dataset.quantityVariantId
8182
);
@@ -143,7 +144,7 @@ class CartItems extends HTMLElement {
143144
];
144145
}
145146

146-
updateQuantity(line, quantity, name, variantId) {
147+
updateQuantity(line, quantity, event, name, variantId) {
147148
this.enableLoading(line);
148149

149150
const body = JSON.stringify({
@@ -152,60 +153,66 @@ class CartItems extends HTMLElement {
152153
sections: this.getSectionsToRender().map((section) => section.section),
153154
sections_url: window.location.pathname,
154155
});
156+
const eventTarget = event.currentTarget instanceof CartRemoveButton ? 'clear' : 'change';
155157

156158
fetch(`${routes.cart_change_url}`, { ...fetchConfig(), ...{ body } })
157159
.then((response) => {
158160
return response.text();
159161
})
160162
.then((state) => {
161-
const parsedState = JSON.parse(state);
162-
const quantityElement =
163-
document.getElementById(`Quantity-${line}`) || document.getElementById(`Drawer-quantity-${line}`);
164-
const items = document.querySelectorAll('.cart-item');
165-
166-
if (parsedState.errors) {
167-
quantityElement.value = quantityElement.getAttribute('value');
168-
this.updateLiveRegions(line, parsedState.errors);
169-
return;
170-
}
171-
172-
this.classList.toggle('is-empty', parsedState.item_count === 0);
173-
const cartDrawerWrapper = document.querySelector('cart-drawer');
174-
const cartFooter = document.getElementById('main-cart-footer');
175-
176-
if (cartFooter) cartFooter.classList.toggle('is-empty', parsedState.item_count === 0);
177-
if (cartDrawerWrapper) cartDrawerWrapper.classList.toggle('is-empty', parsedState.item_count === 0);
178-
179-
this.getSectionsToRender().forEach((section) => {
180-
const elementToReplace =
181-
document.getElementById(section.id).querySelector(section.selector) || document.getElementById(section.id);
182-
elementToReplace.innerHTML = this.getSectionInnerHTML(
183-
parsedState.sections[section.section],
184-
section.selector
185-
);
186-
});
187-
const updatedValue = parsedState.items[line - 1] ? parsedState.items[line - 1].quantity : undefined;
188-
let message = '';
189-
if (items.length === parsedState.items.length && updatedValue !== parseInt(quantityElement.value)) {
190-
if (typeof updatedValue === 'undefined') {
191-
message = window.cartStrings.error;
192-
} else {
193-
message = window.cartStrings.quantityError.replace('[quantity]', updatedValue);
163+
164+
CartPerformance.measure(`${eventTarget}:paint-updated-sections"`, () => {
165+
const parsedState = JSON.parse(state);
166+
const quantityElement =
167+
document.getElementById(`Quantity-${line}`) || document.getElementById(`Drawer-quantity-${line}`);
168+
const items = document.querySelectorAll('.cart-item');
169+
170+
if (parsedState.errors) {
171+
quantityElement.value = quantityElement.getAttribute('value');
172+
this.updateLiveRegions(line, parsedState.errors);
173+
return;
194174
}
195-
}
196-
this.updateLiveRegions(line, message);
197-
198-
const lineItem =
199-
document.getElementById(`CartItem-${line}`) || document.getElementById(`CartDrawer-Item-${line}`);
200-
if (lineItem && lineItem.querySelector(`[name="${name}"]`)) {
201-
cartDrawerWrapper
202-
? trapFocus(cartDrawerWrapper, lineItem.querySelector(`[name="${name}"]`))
203-
: lineItem.querySelector(`[name="${name}"]`).focus();
204-
} else if (parsedState.item_count === 0 && cartDrawerWrapper) {
205-
trapFocus(cartDrawerWrapper.querySelector('.drawer__inner-empty'), cartDrawerWrapper.querySelector('a'));
206-
} else if (document.querySelector('.cart-item') && cartDrawerWrapper) {
207-
trapFocus(cartDrawerWrapper, document.querySelector('.cart-item__name'));
208-
}
175+
176+
this.classList.toggle('is-empty', parsedState.item_count === 0);
177+
const cartDrawerWrapper = document.querySelector('cart-drawer');
178+
const cartFooter = document.getElementById('main-cart-footer');
179+
180+
if (cartFooter) cartFooter.classList.toggle('is-empty', parsedState.item_count === 0);
181+
if (cartDrawerWrapper) cartDrawerWrapper.classList.toggle('is-empty', parsedState.item_count === 0);
182+
183+
this.getSectionsToRender().forEach((section) => {
184+
const elementToReplace =
185+
document.getElementById(section.id).querySelector(section.selector) || document.getElementById(section.id);
186+
elementToReplace.innerHTML = this.getSectionInnerHTML(
187+
parsedState.sections[section.section],
188+
section.selector
189+
);
190+
});
191+
const updatedValue = parsedState.items[line - 1] ? parsedState.items[line - 1].quantity : undefined;
192+
let message = '';
193+
if (items.length === parsedState.items.length && updatedValue !== parseInt(quantityElement.value)) {
194+
if (typeof updatedValue === 'undefined') {
195+
message = window.cartStrings.error;
196+
} else {
197+
message = window.cartStrings.quantityError.replace('[quantity]', updatedValue);
198+
}
199+
}
200+
this.updateLiveRegions(line, message);
201+
202+
const lineItem =
203+
document.getElementById(`CartItem-${line}`) || document.getElementById(`CartDrawer-Item-${line}`);
204+
if (lineItem && lineItem.querySelector(`[name="${name}"]`)) {
205+
cartDrawerWrapper
206+
? trapFocus(cartDrawerWrapper, lineItem.querySelector(`[name="${name}"]`))
207+
: lineItem.querySelector(`[name="${name}"]`).focus();
208+
} else if (parsedState.item_count === 0 && cartDrawerWrapper) {
209+
trapFocus(cartDrawerWrapper.querySelector('.drawer__inner-empty'), cartDrawerWrapper.querySelector('a'));
210+
} else if (document.querySelector('.cart-item') && cartDrawerWrapper) {
211+
trapFocus(cartDrawerWrapper, document.querySelector('.cart-item__name'));
212+
}
213+
});
214+
215+
CartPerformance.measureFromEvent(`${eventTarget}:click-event`, event);
209216

210217
publish(PUB_SUB_EVENTS.cartUpdate, { source: 'cart-items', cartData: parsedState, variantId: variantId });
211218
})

assets/global.js

+32
Original file line numberDiff line numberDiff line change
@@ -1267,3 +1267,35 @@ class BulkAdd extends HTMLElement {
12671267
if (!customElements.get('bulk-add')) {
12681268
customElements.define('bulk-add', BulkAdd);
12691269
}
1270+
1271+
class CartPerformance {
1272+
static #metric_prefix = "cart-performance"
1273+
1274+
static measureFromEvent(benchmarkName, event) {
1275+
const startMarker = performance.mark(`${CartPerformance.#metric_prefix}:${benchmarkName}:start`, {
1276+
startTime: event.timeStamp
1277+
});
1278+
1279+
const endMarker = performance.mark(`${CartPerformance.#metric_prefix}:${benchmarkName}:end`);
1280+
1281+
performance.measure(
1282+
benchmarkName,
1283+
`${benchmarkName}:start`,
1284+
`${benchmarkName}:end`
1285+
);
1286+
}
1287+
1288+
static measure(benchmarkName, callback) {
1289+
const startMarker = performance.mark(`${CartPerformance.#metric_prefix}:${benchmarkName}:start`);
1290+
1291+
callback();
1292+
1293+
const endMarker = performance.mark(`${CartPerformance.#metric_prefix}:${benchmarkName}:end`);
1294+
1295+
performance.measure(
1296+
benchmarkName,
1297+
`${benchmarkName}:start`,
1298+
`${benchmarkName}:end`
1299+
);
1300+
}
1301+
}

assets/product-form.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,18 @@ if (!customElements.get('product-form')) {
7979
'modalClosed',
8080
() => {
8181
setTimeout(() => {
82-
this.cart.renderContents(response);
82+
CartPerformance.measure("add:click-event:paint-updated-sections", () => {
83+
this.cart.renderContents(response);
84+
});
8385
});
8486
},
8587
{ once: true }
8688
);
8789
quickAddModal.hide(true);
8890
} else {
89-
this.cart.renderContents(response);
91+
CartPerformance.measure("add:click-event:paint-updated-sections", () => {
92+
this.cart.renderContents(response);
93+
});
9094
}
9195
})
9296
.catch((e) => {
@@ -97,6 +101,8 @@ if (!customElements.get('product-form')) {
97101
if (this.cart && this.cart.classList.contains('is-empty')) this.cart.classList.remove('is-empty');
98102
if (!this.error) this.submitButton.removeAttribute('aria-disabled');
99103
this.querySelector('.loading__spinner').classList.add('hidden');
104+
105+
CartPerformance.measureFromEvent("add:click-event", evt);
100106
});
101107
}
102108

0 commit comments

Comments
 (0)