@shopify/hydrogen 0.17.2 → 0.17.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/esnext/client.d.ts +2 -0
  3. package/dist/esnext/client.js +2 -0
  4. package/dist/esnext/components/ProductProvider/ProductProvider.client.js +1 -1
  5. package/dist/esnext/foundation/Analytics/ClientAnalytics.d.ts +1 -0
  6. package/dist/esnext/foundation/Analytics/ClientAnalytics.js +7 -1
  7. package/dist/esnext/foundation/Analytics/connectors/PerformanceMetrics/PerformanceMetrics.client.d.ts +7 -0
  8. package/dist/esnext/foundation/Analytics/connectors/PerformanceMetrics/PerformanceMetrics.client.js +64 -0
  9. package/dist/esnext/foundation/Analytics/connectors/PerformanceMetrics/PerformanceMetrics.server.d.ts +1 -0
  10. package/dist/esnext/foundation/Analytics/connectors/PerformanceMetrics/PerformanceMetrics.server.js +24 -0
  11. package/dist/esnext/foundation/Analytics/connectors/PerformanceMetrics/PerformanceMetricsDebug.client.d.ts +1 -0
  12. package/dist/esnext/foundation/Analytics/connectors/PerformanceMetrics/PerformanceMetricsDebug.client.js +23 -0
  13. package/dist/esnext/foundation/Analytics/const.d.ts +1 -0
  14. package/dist/esnext/foundation/Analytics/const.js +1 -0
  15. package/dist/esnext/foundation/Route/Route.server.js +1 -10
  16. package/dist/esnext/hooks/useParsedMetafields/useParsedMetafields.js +0 -2
  17. package/dist/esnext/index.d.ts +1 -0
  18. package/dist/esnext/index.js +1 -0
  19. package/dist/esnext/version.d.ts +1 -1
  20. package/dist/esnext/version.js +1 -1
  21. package/dist/node/foundation/Analytics/ClientAnalytics.d.ts +1 -0
  22. package/dist/node/foundation/Analytics/ClientAnalytics.js +7 -1
  23. package/dist/node/foundation/Analytics/const.d.ts +1 -0
  24. package/dist/node/foundation/Analytics/const.js +1 -0
  25. package/dist/node/version.d.ts +1 -1
  26. package/dist/node/version.js +1 -1
  27. package/package.json +1 -1
  28. package/dist/esnext/foundation/Boomerang/Boomerang.client.d.ts +0 -9
  29. package/dist/esnext/foundation/Boomerang/Boomerang.client.js +0 -66
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.17.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1096](https://github.com/Shopify/hydrogen/pull/1096) [`0a15376e`](https://github.com/Shopify/hydrogen/commit/0a15376ec806054ddd5848d9dbfa6e50a85beb49) Thanks [@wizardlyhel](https://github.com/wizardlyhel)! - Make performance data available with ClientAnalytics and optional for developers to include
8
+
9
+ * [#1209](https://github.com/Shopify/hydrogen/pull/1209) [`d0dada0a`](https://github.com/Shopify/hydrogen/commit/d0dada0a0b3170d2cb885d2f29bbbef0c6d9e9e4) Thanks [@blittle](https://github.com/blittle)! - Make metafields optional within the ProductProvider. Fixes #1127
10
+
3
11
  ## 0.17.2
4
12
 
5
13
  ### Patch Changes
@@ -11,3 +11,5 @@ export { useRouteParams } from './foundation/useRouteParams/useRouteParams';
11
11
  export { useNavigate } from './foundation/useNavigate/useNavigate';
12
12
  export { fetchSync } from './foundation/fetchSync/client/fetchSync';
13
13
  export { suspendFunction, preloadFunction } from './utilities/suspense';
14
+ export { PerformanceMetrics } from './foundation/Analytics/connectors/PerformanceMetrics/PerformanceMetrics.client';
15
+ export { PerformanceMetricsDebug } from './foundation/Analytics/connectors/PerformanceMetrics/PerformanceMetricsDebug.client';
@@ -11,3 +11,5 @@ export { useRouteParams } from './foundation/useRouteParams/useRouteParams';
11
11
  export { useNavigate } from './foundation/useNavigate/useNavigate';
12
12
  export { fetchSync } from './foundation/fetchSync/client/fetchSync';
13
13
  export { suspendFunction, preloadFunction } from './utilities/suspense';
14
+ export { PerformanceMetrics } from './foundation/Analytics/connectors/PerformanceMetrics/PerformanceMetrics.client';
15
+ export { PerformanceMetricsDebug } from './foundation/Analytics/connectors/PerformanceMetrics/PerformanceMetricsDebug.client';
@@ -8,7 +8,7 @@ import { ProductOptionsProvider } from './ProductOptionsProvider.client';
8
8
  * this component can use the `useProduct` hook.
9
9
  */
10
10
  export function ProductProvider({ children, data: product, initialVariantId, }) {
11
- const metafields = useParsedMetafields(product.metafields);
11
+ const metafields = useParsedMetafields(product.metafields || {});
12
12
  // @ts-expect-error The types here are broken on main, need to come back and fix them sometime
13
13
  const providerValue = useMemo(() => {
14
14
  return {
@@ -19,6 +19,7 @@ export declare const ClientAnalytics: {
19
19
  REMOVE_FROM_CART: string;
20
20
  UPDATE_CART: string;
21
21
  DISCOUNT_CODE_UPDATED: string;
22
+ PERFORMANCE: string;
22
23
  };
23
24
  };
24
25
  export {};
@@ -78,7 +78,13 @@ function subscribe(eventname, callbackFunction) {
78
78
  };
79
79
  }
80
80
  function pushToServer(init, searchParam) {
81
- return fetch(`${EVENT_PATHNAME}${searchParam ? `?${searchParam}` : ''}`, init);
81
+ return fetch(`${EVENT_PATHNAME}${searchParam ? `?${searchParam}` : ''}`, Object.assign({
82
+ method: 'post',
83
+ headers: {
84
+ 'cache-control': 'no-cache',
85
+ 'Content-Type': 'application/json',
86
+ },
87
+ }, init));
82
88
  }
83
89
  export const ClientAnalytics = {
84
90
  pushToPageAnalyticsData,
@@ -0,0 +1,7 @@
1
+ declare global {
2
+ interface Window {
3
+ BOOMR: any;
4
+ BOOMR_onload: any;
5
+ }
6
+ }
7
+ export declare function PerformanceMetrics(): null;
@@ -0,0 +1,64 @@
1
+ import { useEffect } from 'react';
2
+ import { loadScript } from '../../../../utilities';
3
+ import { ClientAnalytics } from '../../index';
4
+ import { useShop } from '../../../useShop';
5
+ const URL = 'https://cdn.shopify.com/shopifycloud/boomerang/shopify-boomerang-hydrogen.min.js';
6
+ export function PerformanceMetrics() {
7
+ const { storeDomain } = useShop();
8
+ useEffect(() => {
9
+ try {
10
+ (function () {
11
+ if (window.BOOMR &&
12
+ (window.BOOMR.version || window.BOOMR.snippetExecuted)) {
13
+ return;
14
+ }
15
+ // Executes only on first mount
16
+ window.BOOMR = window.BOOMR || {};
17
+ window.BOOMR.hydrogenPerformanceEvent = (data) => {
18
+ ClientAnalytics.publish(ClientAnalytics.eventNames.PERFORMANCE, true, data);
19
+ ClientAnalytics.pushToServer({
20
+ body: JSON.stringify(data),
21
+ }, ClientAnalytics.eventNames.PERFORMANCE);
22
+ };
23
+ window.BOOMR.storeDomain = storeDomain;
24
+ function boomerangSaveLoadTime(e) {
25
+ window.BOOMR_onload = (e && e.timeStamp) || Date.now();
26
+ }
27
+ // @ts-ignore
28
+ function boomerangInit(e) {
29
+ e.detail.BOOMR.init();
30
+ e.detail.BOOMR.t_end = Date.now();
31
+ }
32
+ if (window.addEventListener) {
33
+ window.addEventListener('load', boomerangSaveLoadTime, false);
34
+ // @ts-ignore
35
+ }
36
+ else if (window.attachEvent) {
37
+ // @ts-ignore
38
+ window.attachEvent('onload', boomerangSaveLoadTime);
39
+ }
40
+ if (document.addEventListener) {
41
+ document.addEventListener('onBoomerangLoaded', boomerangInit);
42
+ // @ts-ignore
43
+ }
44
+ else if (document.attachEvent) {
45
+ // @ts-ignore
46
+ document.attachEvent('onpropertychange', function (e) {
47
+ if (!e)
48
+ e = event;
49
+ if (e.propertyName === 'onBoomerangLoaded')
50
+ boomerangInit(e);
51
+ });
52
+ }
53
+ })();
54
+ loadScript(URL).catch(() => {
55
+ // ignore if boomerang doesn't load
56
+ // most likely because of an ad blocker
57
+ });
58
+ }
59
+ catch (err) {
60
+ // Do nothing
61
+ }
62
+ }, [storeDomain]);
63
+ return null;
64
+ }
@@ -0,0 +1 @@
1
+ export declare function request(request: Request, data?: any, contentType?: string): void;
@@ -0,0 +1,24 @@
1
+ export function request(request, data, contentType) {
2
+ const url = new URL(request.url);
3
+ if (url.search === '?performance' && contentType === 'json') {
4
+ const initTime = new Date().getTime();
5
+ fetch('https://monorail-edge.shopifysvc.com/v1/produce', {
6
+ method: 'post',
7
+ headers: {
8
+ 'content-type': 'text/plain',
9
+ 'x-forwarded-for': request.headers.get('x-forwarded-for') || '',
10
+ 'user-agent': request.headers.get('user-agent') || '',
11
+ },
12
+ body: JSON.stringify({
13
+ schema_id: 'hydrogen_buyer_performance/2.0',
14
+ payload: data,
15
+ metadata: {
16
+ event_created_at_ms: initTime,
17
+ event_sent_at_ms: new Date().getTime(),
18
+ },
19
+ }),
20
+ }).catch((error) => {
21
+ // send to bugsnag? oxygen?
22
+ });
23
+ }
24
+ }
@@ -0,0 +1 @@
1
+ export declare function PerformanceMetricsDebug(): null;
@@ -0,0 +1,23 @@
1
+ import { useEffect } from 'react';
2
+ import { ClientAnalytics } from '../../index';
3
+ const PAD = 10;
4
+ let isInit = false;
5
+ export function PerformanceMetricsDebug() {
6
+ useEffect(() => {
7
+ if (!isInit) {
8
+ isInit = true;
9
+ ClientAnalytics.subscribe(ClientAnalytics.eventNames.PERFORMANCE, (data) => {
10
+ console.group(`Performance - ${data.page_load_type} load`);
11
+ logMetricIf('TTFB:', data.response_start - data.navigation_start);
12
+ logMetricIf('FCP:', data.first_contentful_paint);
13
+ logMetricIf('LCP:', data.largest_contentful_paint);
14
+ logMetricIf('Duration:', data.response_end - data.navigation_start);
15
+ console.groupEnd();
16
+ });
17
+ }
18
+ });
19
+ return null;
20
+ }
21
+ function logMetricIf(lable, data) {
22
+ data && console.log(`${lable.padEnd(PAD)}${Math.round(data)} ms`);
23
+ }
@@ -5,4 +5,5 @@ export declare const eventNames: {
5
5
  REMOVE_FROM_CART: string;
6
6
  UPDATE_CART: string;
7
7
  DISCOUNT_CODE_UPDATED: string;
8
+ PERFORMANCE: string;
8
9
  };
@@ -5,4 +5,5 @@ export const eventNames = {
5
5
  REMOVE_FROM_CART: 'remove-from-cart',
6
6
  UPDATE_CART: 'update-cart',
7
7
  DISCOUNT_CODE_UPDATED: 'discount-code-updated',
8
+ PERFORMANCE: 'performance',
8
9
  };
@@ -1,15 +1,12 @@
1
1
  import React, { cloneElement } from 'react';
2
2
  import { useServerRequest } from '../ServerRequestProvider';
3
3
  import { matchPath } from '../../utilities/matchPath';
4
- import { Boomerang } from '../Boomerang/Boomerang.client';
5
4
  import { RouteParamsProvider } from '../useRouteParams/RouteParamsProvider.client';
6
- import { useServerAnalytics } from '../Analytics';
7
5
  /**
8
6
  * The `Route` component is used to set up a route in Hydrogen that's independent of the file system. Routes are
9
7
  * matched in the order that they're defined.
10
8
  */
11
9
  export function Route({ path, page }) {
12
- var _a;
13
10
  const request = useServerRequest();
14
11
  const { routeRendered, serverProps } = request.ctx.router;
15
12
  if (routeRendered)
@@ -25,13 +22,7 @@ export function Route({ path, page }) {
25
22
  if (match) {
26
23
  request.ctx.router.routeRendered = true;
27
24
  request.ctx.router.routeParams = match.params;
28
- const name = (_a = page === null || page === void 0 ? void 0 : page.type) === null || _a === void 0 ? void 0 : _a.name;
29
- useServerAnalytics({
30
- templateName: name,
31
- });
32
- return (React.createElement(RouteParamsProvider, { routeParams: match.params },
33
- cloneElement(page, { params: match.params || {}, ...serverProps }),
34
- name ? React.createElement(Boomerang, { pageTemplate: name }) : null));
25
+ return (React.createElement(RouteParamsProvider, { routeParams: match.params }, cloneElement(page, { params: match.params || {}, ...serverProps })));
35
26
  }
36
27
  return null;
37
28
  }
@@ -7,8 +7,6 @@ import { flattenConnection, parseMetafieldValue } from '../../utilities';
7
7
  export function useParsedMetafields(
8
8
  /** A [MetafieldConnection](https://shopify.dev/api/storefront/reference/common-objects/metafieldconnection). */
9
9
  metafields) {
10
- var _a, _b;
11
- (_b = (_a = metafields === null || metafields === void 0 ? void 0 : metafields.edges) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.node;
12
10
  return useMemo(() => {
13
11
  if (!metafields) {
14
12
  throw new Error(`'useParsedMetafields' needs metafields`);
@@ -15,6 +15,7 @@ export { CartQuery } from './components/CartProvider/cart-queries';
15
15
  export { generateCacheControlHeader, NoStore, CacheSeconds, CacheMinutes, CacheHours, CacheDays, CacheWeeks, CacheMonths, CacheCustom, } from './framework/CachingStrategy';
16
16
  export { fetchSync } from './foundation/fetchSync/server/fetchSync';
17
17
  export { useServerAnalytics } from './foundation/Analytics';
18
+ export * as PerformanceMetricsServerAnalyticsConnector from './foundation/Analytics/connectors/PerformanceMetrics/PerformanceMetrics.server';
18
19
  export { useSession } from './foundation/useSession/useSession';
19
20
  export { CookieSessionStorage } from './foundation/CookieSessionStorage/CookieSessionStorage';
20
21
  export { MemorySessionStorage } from './foundation/MemorySessionStorage/MemorySessionStorage';
@@ -19,6 +19,7 @@ export { CartQuery } from './components/CartProvider/cart-queries';
19
19
  export { generateCacheControlHeader, NoStore, CacheSeconds, CacheMinutes, CacheHours, CacheDays, CacheWeeks, CacheMonths, CacheCustom, } from './framework/CachingStrategy';
20
20
  export { fetchSync } from './foundation/fetchSync/server/fetchSync';
21
21
  export { useServerAnalytics } from './foundation/Analytics';
22
+ export * as PerformanceMetricsServerAnalyticsConnector from './foundation/Analytics/connectors/PerformanceMetrics/PerformanceMetrics.server';
22
23
  export { useSession } from './foundation/useSession/useSession';
23
24
  export { CookieSessionStorage } from './foundation/CookieSessionStorage/CookieSessionStorage';
24
25
  export { MemorySessionStorage } from './foundation/MemorySessionStorage/MemorySessionStorage';
@@ -1 +1 @@
1
- export declare const LIB_VERSION = "0.17.2";
1
+ export declare const LIB_VERSION = "0.17.3";
@@ -1 +1 @@
1
- export const LIB_VERSION = '0.17.2';
1
+ export const LIB_VERSION = '0.17.3';
@@ -19,6 +19,7 @@ export declare const ClientAnalytics: {
19
19
  REMOVE_FROM_CART: string;
20
20
  UPDATE_CART: string;
21
21
  DISCOUNT_CODE_UPDATED: string;
22
+ PERFORMANCE: string;
22
23
  };
23
24
  };
24
25
  export {};
@@ -81,7 +81,13 @@ function subscribe(eventname, callbackFunction) {
81
81
  };
82
82
  }
83
83
  function pushToServer(init, searchParam) {
84
- return fetch(`${constants_1.EVENT_PATHNAME}${searchParam ? `?${searchParam}` : ''}`, init);
84
+ return fetch(`${constants_1.EVENT_PATHNAME}${searchParam ? `?${searchParam}` : ''}`, Object.assign({
85
+ method: 'post',
86
+ headers: {
87
+ 'cache-control': 'no-cache',
88
+ 'Content-Type': 'application/json',
89
+ },
90
+ }, init));
85
91
  }
86
92
  exports.ClientAnalytics = {
87
93
  pushToPageAnalyticsData,
@@ -5,4 +5,5 @@ export declare const eventNames: {
5
5
  REMOVE_FROM_CART: string;
6
6
  UPDATE_CART: string;
7
7
  DISCOUNT_CODE_UPDATED: string;
8
+ PERFORMANCE: string;
8
9
  };
@@ -8,4 +8,5 @@ exports.eventNames = {
8
8
  REMOVE_FROM_CART: 'remove-from-cart',
9
9
  UPDATE_CART: 'update-cart',
10
10
  DISCOUNT_CODE_UPDATED: 'discount-code-updated',
11
+ PERFORMANCE: 'performance',
11
12
  };
@@ -1 +1 @@
1
- export declare const LIB_VERSION = "0.17.2";
1
+ export declare const LIB_VERSION = "0.17.3";
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LIB_VERSION = void 0;
4
- exports.LIB_VERSION = '0.17.2';
4
+ exports.LIB_VERSION = '0.17.3';
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "engines": {
8
8
  "node": ">=14"
9
9
  },
10
- "version": "0.17.2",
10
+ "version": "0.17.3",
11
11
  "description": "Modern custom Shopify storefronts",
12
12
  "license": "MIT",
13
13
  "main": "dist/esnext/index.js",
@@ -1,9 +0,0 @@
1
- declare global {
2
- interface Window {
3
- BOOMR: any;
4
- BOOMR_onload: any;
5
- }
6
- }
7
- export declare function Boomerang({ pageTemplate }: {
8
- pageTemplate: string | null;
9
- }): null;
@@ -1,66 +0,0 @@
1
- import { useEffect } from 'react';
2
- import { loadScript } from '../../utilities';
3
- import { useShop } from '../useShop';
4
- const URL = 'https://cdn.shopify.com/shopifycloud/boomerang/shopify-boomerang-hydrogen.min.js';
5
- export function Boomerang({ pageTemplate }) {
6
- const { storeDomain } = useShop();
7
- const templateName = pageTemplate && pageTemplate !== null
8
- ? pageTemplate.toLowerCase()
9
- : 'not-set';
10
- useEffect(() => {
11
- (function () {
12
- function boomerangAddVar() {
13
- if (window.BOOMR && window.BOOMR.addVar) {
14
- window.BOOMR.addVar('page_template', templateName);
15
- }
16
- }
17
- // Executes on every mount
18
- boomerangAddVar();
19
- if (window.BOOMR &&
20
- (window.BOOMR.version || window.BOOMR.snippetExecuted)) {
21
- return;
22
- }
23
- // Executes only on first mount
24
- window.BOOMR = window.BOOMR || {};
25
- window.BOOMR.storeDomain = storeDomain;
26
- window.BOOMR.pageTemplate = templateName;
27
- function boomerangSaveLoadTime(e) {
28
- window.BOOMR_onload = (e && e.timeStamp) || Date.now();
29
- }
30
- // @ts-ignore
31
- function boomerangInit(e) {
32
- e.detail.BOOMR.init({
33
- producer_url: 'https://monorail-edge.shopifysvc.com/v1/produce',
34
- });
35
- e.detail.BOOMR.t_end = Date.now();
36
- boomerangAddVar();
37
- }
38
- if (window.addEventListener) {
39
- window.addEventListener('load', boomerangSaveLoadTime, false);
40
- // @ts-ignore
41
- }
42
- else if (window.attachEvent) {
43
- // @ts-ignore
44
- window.attachEvent('onload', boomerangSaveLoadTime);
45
- }
46
- if (document.addEventListener) {
47
- document.addEventListener('onBoomerangLoaded', boomerangInit);
48
- // @ts-ignore
49
- }
50
- else if (document.attachEvent) {
51
- // @ts-ignore
52
- document.attachEvent('onpropertychange', function (e) {
53
- if (!e)
54
- e = event;
55
- if (e.propertyName === 'onBoomerangLoaded')
56
- boomerangInit(e);
57
- });
58
- }
59
- })();
60
- loadScript(URL).catch(() => {
61
- // ignore if boomerang doesn't load
62
- // most likely because of a ad blocker
63
- });
64
- }, [storeDomain, pageTemplate]);
65
- return null;
66
- }