Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -102,73 +102,3 @@ export const CART_QUERY_FRAGMENT = `#graphql
}
}
` as const;

const MENU_FRAGMENT = `#graphql
fragment MenuItem on MenuItem {
id
resourceId
tags
title
type
url
}
fragment ChildMenuItem on MenuItem {
...MenuItem
}
fragment ParentMenuItem on MenuItem {
...MenuItem
items {
...ChildMenuItem
}
}
fragment Menu on Menu {
id
items {
...ParentMenuItem
}
}
` as const;

export const HEADER_QUERY = `#graphql
fragment Shop on Shop {
id
name
description
primaryDomain {
url
}
brand {
logo {
image {
url
}
}
}
}
query Header(
$country: CountryCode
$headerMenuHandle: String!
$language: LanguageCode
) @inContext(language: $language, country: $country) {
shop {
...Shop
}
menu(handle: $headerMenuHandle) {
...Menu
}
}
${MENU_FRAGMENT}
` as const;

export const FOOTER_QUERY = `#graphql
query Footer(
$country: CountryCode
$footerMenuHandle: String!
$language: LanguageCode
) @inContext(language: $language, country: $country) {
menu(handle: $footerMenuHandle) {
...Menu
}
}
${MENU_FRAGMENT}
` as const;
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
Scripts,
ScrollRestoration,
} from 'react-router';
import { FOOTER_QUERY, HEADER_QUERY } from '~/lib/fragments';

import { useNonce } from '@shopify/hydrogen';

Expand Down Expand Up @@ -56,17 +55,11 @@ export function links() {
}

export async function loader(args: LoaderFunctionArgs) {
// Start fetching non-critical data without blocking time to first byte
const deferredData = loadDeferredData(args);

// Await the critical data required to render initial state of the page
const criticalData = await loadCriticalData(args);

const { env } = args.context;
const { env, customerAccount, cart } = args.context;

return {
...deferredData,
...criticalData,
cart: cart.get(),
isLoggedIn: customerAccount.isLoggedIn(),
ENV: {
sentryTrace: env.SENTRY_TRACE,
sentryBaggage: env.SENTRY_BAGGAGE,
Expand All @@ -83,54 +76,6 @@ export async function loader(args: LoaderFunctionArgs) {
};
}

/**
* Load data necessary for rendering content above the fold. This is the critical data
* needed to render the page. If it's unavailable, the whole page should 400 or 500 error.
*/
async function loadCriticalData({ context }: LoaderFunctionArgs) {
const { storefront } = context;

const [header] = await Promise.all([
storefront.query(HEADER_QUERY, {
cache: storefront.CacheLong(),
variables: {
headerMenuHandle: 'main-menu', // Adjust to your header menu handle
},
}),
// Add other queries here, so that they are loaded in parallel
]);

return { header };
}

/**
* Load data for rendering content below the fold. This data is deferred and will be
* fetched after the initial page load. If it's unavailable, the page should still 200.
* Make sure to not throw any errors here, as it will cause the page to 500.
*/
function loadDeferredData({ context }: LoaderFunctionArgs) {
const { storefront, customerAccount, cart } = context;

// defer the footer query (below the fold)
const footer = storefront
.query(FOOTER_QUERY, {
cache: storefront.CacheLong(),
variables: {
footerMenuHandle: 'footer', // Adjust to your footer menu handle
},
})
.catch((error: any) => {
// Log query errors, but don't throw them so the page can still render
console.error(error);
return null;
});
return {
cart: cart.get(),
isLoggedIn: customerAccount.isLoggedIn(),
footer,
};
}

export function Layout({ children }: { children?: React.ReactNode }) {
const nonce = useNonce();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,73 +102,3 @@ export const CART_QUERY_FRAGMENT = `#graphql
}
}
` as const;

const MENU_FRAGMENT = `#graphql
fragment MenuItem on MenuItem {
id
resourceId
tags
title
type
url
}
fragment ChildMenuItem on MenuItem {
...MenuItem
}
fragment ParentMenuItem on MenuItem {
...MenuItem
items {
...ChildMenuItem
}
}
fragment Menu on Menu {
id
items {
...ParentMenuItem
}
}
` as const;

export const HEADER_QUERY = `#graphql
fragment Shop on Shop {
id
name
description
primaryDomain {
url
}
brand {
logo {
image {
url
}
}
}
}
query Header(
$country: CountryCode
$headerMenuHandle: String!
$language: LanguageCode
) @inContext(language: $language, country: $country) {
shop {
...Shop
}
menu(handle: $headerMenuHandle) {
...Menu
}
}
${MENU_FRAGMENT}
` as const;

export const FOOTER_QUERY = `#graphql
query Footer(
$country: CountryCode
$footerMenuHandle: String!
$language: LanguageCode
) @inContext(language: $language, country: $country) {
menu(handle: $footerMenuHandle) {
...Menu
}
}
${MENU_FRAGMENT}
` as const;
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,7 @@ export function links() {
}

export async function loader({ context }: { context: LoaderFunctionArgs['context'] }) {
const { storefront, session, cart } = context as {
storefront: {
query: (query: string, options: any) => Promise<any>;
CacheLong: () => any;
};
const { session, cart } = context as {
session: HydrogenSession;
cart: unknown;
env: unknown;
Expand All @@ -68,27 +64,9 @@ export async function loader({ context }: { context: LoaderFunctionArgs['context
// defer the cart query by not awaiting it
const cartPromise = typedCart.get();

// defer the footer query (below the fold)
const footerPromise = storefront.query(FOOTER_QUERY, {
cache: storefront.CacheLong(),
variables: {
footerMenuHandle: 'footer', // Adjust to your footer menu handle
},
});

// await the header query (above the fold)
const headerPromise = storefront.query(HEADER_QUERY, {
cache: storefront.CacheLong(),
variables: {
headerMenuHandle: 'main-menu', // Adjust to your header menu handle
},
});

return defer(
{
cart: cartPromise,
footer: footerPromise,
header: await headerPromise,
isLoggedIn,
publicStoreDomain,
},
Expand Down Expand Up @@ -225,73 +203,3 @@ async function validateCustomerAccessToken(session: HydrogenSession, customerAcc

return { isLoggedIn, headers };
}
Comment thread
isaacs marked this conversation as resolved.

const MENU_FRAGMENT = `#graphql
fragment MenuItem on MenuItem {
id
resourceId
tags
title
type
url
}
fragment ChildMenuItem on MenuItem {
...MenuItem
}
fragment ParentMenuItem on MenuItem {
...MenuItem
items {
...ChildMenuItem
}
}
fragment Menu on Menu {
id
items {
...ParentMenuItem
}
}
` as const;

const HEADER_QUERY = `#graphql
fragment Shop on Shop {
id
name
description
primaryDomain {
url
}
brand {
logo {
image {
url
}
}
}
}
query Header(
$country: CountryCode
$headerMenuHandle: String!
$language: LanguageCode
) @inContext(language: $language, country: $country) {
shop {
...Shop
}
menu(handle: $headerMenuHandle) {
...Menu
}
}
${MENU_FRAGMENT}
` as const;

const FOOTER_QUERY = `#graphql
query Footer(
$country: CountryCode
$footerMenuHandle: String!
$language: LanguageCode
) @inContext(language: $language, country: $country) {
menu(handle: $footerMenuHandle) {
...Menu
}
}
${MENU_FRAGMENT}
` as const;
Loading