From 97083ffd778dca7b4cf2593bac62cdc9fa2bd73a Mon Sep 17 00:00:00 2001 From: Pedro Soares Date: Tue, 21 Jan 2025 16:56:57 -0300 Subject: [PATCH 1/8] feat: next seo poc --- packages/core/src/pages/s.tsx | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/packages/core/src/pages/s.tsx b/packages/core/src/pages/s.tsx index 5e8187ff60..f128d99e41 100644 --- a/packages/core/src/pages/s.tsx +++ b/packages/core/src/pages/s.tsx @@ -1,4 +1,4 @@ -import type { GetStaticProps } from 'next' +import type { GetServerSideProps } from 'next' import { NextSeo } from 'next-seo' import { useRouter } from 'next/router' import { useMemo } from 'react' @@ -26,6 +26,7 @@ import { getPage, SearchContentType } from 'src/server/cms' type Props = { page: SearchContentType globalSections: GlobalSectionsData + searchTerm: string } export interface SearchPageContextType { @@ -54,13 +55,13 @@ const useSearchParams = ({ }, [asPath, defaultSort]) } -function Page({ page: searchContentType, globalSections }: Props) { +function Page({ page: searchContentType, globalSections, searchTerm }: Props) { const { settings } = searchContentType const applySearchState = useApplySearchState() const searchParams = useSearchParams({ sort: settings?.productGallery?.sortBySelection as SearchState['sort'], }) - + console.log({ searchTerm }) const title = 'Search Results' const { description, titleTemplate } = storeConfig.seo const itemsPerPage = settings?.productGallery?.itemsPerPage ?? ITEMS_PER_PAGE @@ -78,8 +79,8 @@ function Page({ page: searchContentType, globalSections }: Props) { {/* SEO */} , Locator -> = async ({ previewData }) => { +> = async (context) => { + const { previewData, query } = context + + const searchTerm = query.q as string const globalSections = await getGlobalSectionsData(previewData) if (storeConfig.cms.data) { @@ -133,7 +137,7 @@ export const getStaticProps: GetStaticProps< }) return { - props: { page: pageData, globalSections }, + props: { page: pageData, globalSections, searchTerm }, } } } @@ -147,6 +151,7 @@ export const getStaticProps: GetStaticProps< props: { page, globalSections, + searchTerm, }, } } From 16b69bdade9902a9692827b12f22aaa4baa562ef Mon Sep 17 00:00:00 2001 From: Pedro Soares Date: Thu, 23 Jan 2025 09:06:06 -0300 Subject: [PATCH 2/8] feat: add cache control headers --- packages/core/src/pages/s.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/core/src/pages/s.tsx b/packages/core/src/pages/s.tsx index f128d99e41..00913afd63 100644 --- a/packages/core/src/pages/s.tsx +++ b/packages/core/src/pages/s.tsx @@ -61,7 +61,7 @@ function Page({ page: searchContentType, globalSections, searchTerm }: Props) { const searchParams = useSearchParams({ sort: settings?.productGallery?.sortBySelection as SearchState['sort'], }) - console.log({ searchTerm }) + const title = 'Search Results' const { description, titleTemplate } = storeConfig.seo const itemsPerPage = settings?.productGallery?.itemsPerPage ?? ITEMS_PER_PAGE @@ -120,9 +120,10 @@ export const getServerSideProps: GetServerSideProps< Record, Locator > = async (context) => { - const { previewData, query } = context + const { previewData, query, res } = context + + const searchTerm = (query.q as string)?.split('+').join(' ') - const searchTerm = query.q as string const globalSections = await getGlobalSectionsData(previewData) if (storeConfig.cms.data) { @@ -147,6 +148,11 @@ export const getServerSideProps: GetServerSideProps< contentType: 'search', }) + res.setHeader( + 'Cache-Control', + 'public, s-maxage=300, stale-while-revalidate=31536000' + ) // 5 minutes of fresh content and 1 year of stale content + return { props: { page, From 827fa701eaddc3e9d3364d03804d8b7f1a7a5aa3 Mon Sep 17 00:00:00 2001 From: Pedro Soares Date: Fri, 24 Jan 2025 10:41:38 -0300 Subject: [PATCH 3/8] feat: test ssr flag --- packages/core/discovery.config.default.js | 1 + packages/core/src/pages/s.tsx | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/packages/core/discovery.config.default.js b/packages/core/discovery.config.default.js index 7fc9631f7f..5bdb38a7c4 100644 --- a/packages/core/discovery.config.default.js +++ b/packages/core/discovery.config.default.js @@ -106,5 +106,6 @@ module.exports = { noRobots: false, preact: false, enableRedirects: false, + enableSearchSSR: true, }, } diff --git a/packages/core/src/pages/s.tsx b/packages/core/src/pages/s.tsx index 00913afd63..efc614c9d5 100644 --- a/packages/core/src/pages/s.tsx +++ b/packages/core/src/pages/s.tsx @@ -26,7 +26,7 @@ import { getPage, SearchContentType } from 'src/server/cms' type Props = { page: SearchContentType globalSections: GlobalSectionsData - searchTerm: string + searchTerm?: string } export interface SearchPageContextType { @@ -70,6 +70,14 @@ function Page({ page: searchContentType, globalSections, searchTerm }: Props) { return null } + const isSSREnabled = storeConfig.experimental.enableSearchSSR + + const currentSearchTerm = isSSREnabled ? searchTerm : searchParams.term + const currentTitle = isSSREnabled ? searchTerm : title + const currentDescription = isSSREnabled + ? `${searchTerm}: em promoção que você procura? Na Americanas você encontra as melhores ofertas de produtos com entrega rápida. Vem!` + : description + return ( - + {/* WARNING: Do not import or render components from any @@ -107,7 +115,7 @@ function Page({ page: searchContentType, globalSections, searchTerm }: Props) { searchContentType={searchContentType} serverData={{ title, - searchTerm: searchParams.term ?? undefined, + searchTerm: currentSearchTerm ?? undefined, }} globalSections={globalSections.sections} /> From 38ada08a0c58c286014773b69bcf0ea8d79be209 Mon Sep 17 00:00:00 2001 From: Pedro Soares Date: Mon, 27 Jan 2025 16:17:18 -0300 Subject: [PATCH 4/8] feat: generate SSR in search based on a flag --- packages/cli/src/utils/generate.ts | 80 +++++++++++++++++++++++ packages/core/discovery.config.default.js | 9 ++- packages/core/src/pages/s.tsx | 30 ++++----- 3 files changed, 101 insertions(+), 18 deletions(-) diff --git a/packages/cli/src/utils/generate.ts b/packages/cli/src/utils/generate.ts index 16ca0bf065..bca1021c87 100644 --- a/packages/cli/src/utils/generate.ts +++ b/packages/cli/src/utils/generate.ts @@ -489,6 +489,85 @@ function enableRedirectsMiddleware(basePath: string) { } } +const GET_SERVER_SIDE_PROPS = ` + export const getServerSideProps: GetServerSideProps< + Props, + Record, + Locator +> = async (context) => { + const { previewData, query, res } = context + + const searchTerm = (query.q as string)?.split('+').join(' ') + + const globalSections = await getGlobalSectionsData(previewData) + + if (storeConfig.cms.data) { + const cmsData = JSON.parse(storeConfig.cms.data) + const page = cmsData['search'][0] + + if (page) { + const pageData = await getPage({ + contentType: 'search', + documentId: page.documentId, + versionId: page.versionId, + }) + + return { + props: { page: pageData, globalSections, searchTerm }, + } + } + } + + const page = await getPage({ + ...(previewData?.contentType === 'search' ? previewData : null), + contentType: 'search', + }) + + res.setHeader( + 'Cache-Control', + 'public, s-maxage=300, stale-while-revalidate=31536000' + ) // 5 minutes of fresh content and 1 year of stale content + + return { + props: { + page, + globalSections, + searchTerm, + }, + } +} +` + +const GET_STATIC_PROPS_REGEX = /export const getStaticProps: GetStaticProps<[\s\S]*?>\s*= async \(context\) => \{[\s\S]*?\}/ + + +function enableSearchSSR(basePath: string) { + const storeConfigPath = getCurrentUserStoreConfigFile(basePath) + + if(!storeConfigPath) { + return + } + const storeConfig = require(storeConfigPath) + if(!storeConfig.experimental.enableSearchSSR) { + return + } + + const { tmpDir } = withBasePath(basePath) + + const searchPagePath = path.join(tmpDir, 'src', 'pages', 's.tsx') + + const searchPageData = String(readFileSync(searchPagePath)) + let searchPageWithSSR = searchPageData.replace( + GET_STATIC_PROPS_REGEX, + GET_SERVER_SIDE_PROPS + ) + + searchPageWithSSR.replace("import type { GetStaticProps } from 'next'", "import type { GetServerSideProps } from 'next'") + + writeFileSync(searchPagePath, searchPageWithSSR) + +} + export async function generate(options: GenerateOptions) { const { basePath, setup = false } = options @@ -508,6 +587,7 @@ export async function generate(options: GenerateOptions) { await Promise.all([ setupPromise, checkDependencies(basePath, ['typescript']), + enableSearchSSR(basePath), updateBuildTime(basePath), copyUserStarterToCustomizations(basePath), copyTheme(basePath), diff --git a/packages/core/discovery.config.default.js b/packages/core/discovery.config.default.js index 5bdb38a7c4..538b0c6b64 100644 --- a/packages/core/discovery.config.default.js +++ b/packages/core/discovery.config.default.js @@ -6,7 +6,12 @@ module.exports = { author: 'Store Framework', plp: { titleTemplate: '%s | FastStore PLP', - descriptionTemplate: '%s products on FastStore Product Listing Page', + descriptionTemplate: '%s products on FastStore Product Listing Page' + }, + search: { + titleTemplate: '%s: Search results title', + descriptionTemplate: '%s: Search results description', + title: 'Search Results', }, }, @@ -106,6 +111,6 @@ module.exports = { noRobots: false, preact: false, enableRedirects: false, - enableSearchSSR: true, + enableSearchSSR: false, }, } diff --git a/packages/core/src/pages/s.tsx b/packages/core/src/pages/s.tsx index efc614c9d5..db952d609c 100644 --- a/packages/core/src/pages/s.tsx +++ b/packages/core/src/pages/s.tsx @@ -1,4 +1,4 @@ -import type { GetServerSideProps } from 'next' +import type { GetStaticProps } from 'next' import { NextSeo } from 'next-seo' import { useRouter } from 'next/router' import { useMemo } from 'react' @@ -62,22 +62,27 @@ function Page({ page: searchContentType, globalSections, searchTerm }: Props) { sort: settings?.productGallery?.sortBySelection as SearchState['sort'], }) - const title = 'Search Results' - const { description, titleTemplate } = storeConfig.seo + const { description, titleTemplate, search } = storeConfig.seo const itemsPerPage = settings?.productGallery?.itemsPerPage ?? ITEMS_PER_PAGE if (!searchParams) { return null } + const title = search?.title ?? 'Search Results' + const currentTitleTemplate = search?.titleTemplate ?? titleTemplate const isSSREnabled = storeConfig.experimental.enableSearchSSR const currentSearchTerm = isSSREnabled ? searchTerm : searchParams.term const currentTitle = isSSREnabled ? searchTerm : title const currentDescription = isSSREnabled - ? `${searchTerm}: em promoção que você procura? Na Americanas você encontra as melhores ofertas de produtos com entrega rápida. Vem!` + ? search.descriptionTemplate.replace(/%s/g, () => searchTerm) : description + const canonical = currentSearchTerm + ? `${storeConfig.storeUrl}?s=${currentSearchTerm}` + : undefined + return ( {/* SEO */} , Locator > = async (context) => { - const { previewData, query, res } = context - - const searchTerm = (query.q as string)?.split('+').join(' ') + const { previewData } = context const globalSections = await getGlobalSectionsData(previewData) @@ -146,7 +150,7 @@ export const getServerSideProps: GetServerSideProps< }) return { - props: { page: pageData, globalSections, searchTerm }, + props: { page: pageData, globalSections }, } } } @@ -156,16 +160,10 @@ export const getServerSideProps: GetServerSideProps< contentType: 'search', }) - res.setHeader( - 'Cache-Control', - 'public, s-maxage=300, stale-while-revalidate=31536000' - ) // 5 minutes of fresh content and 1 year of stale content - return { props: { page, globalSections, - searchTerm, }, } } From 11e9f23dc24bd3bad5b9e1dbecd2b6a67f837092 Mon Sep 17 00:00:00 2001 From: Pedro Soares Date: Mon, 27 Jan 2025 18:33:00 -0300 Subject: [PATCH 5/8] feat: cli new approach --- packages/cli/src/utils/generate.ts | 59 +---------------- .../getServerSideProps.ts | 51 +++++++++++++++ .../getStaticProps.ts | 53 ++++++++++++++++ .../searchServerSideFunctions/index.ts | 2 + packages/core/src/pages/s.tsx | 63 ++++--------------- 5 files changed, 118 insertions(+), 110 deletions(-) create mode 100644 packages/core/src/experimental/searchServerSideFunctions/getServerSideProps.ts create mode 100644 packages/core/src/experimental/searchServerSideFunctions/getStaticProps.ts create mode 100644 packages/core/src/experimental/searchServerSideFunctions/index.ts diff --git a/packages/cli/src/utils/generate.ts b/packages/cli/src/utils/generate.ts index bca1021c87..70a25f9dff 100644 --- a/packages/cli/src/utils/generate.ts +++ b/packages/cli/src/utils/generate.ts @@ -489,56 +489,6 @@ function enableRedirectsMiddleware(basePath: string) { } } -const GET_SERVER_SIDE_PROPS = ` - export const getServerSideProps: GetServerSideProps< - Props, - Record, - Locator -> = async (context) => { - const { previewData, query, res } = context - - const searchTerm = (query.q as string)?.split('+').join(' ') - - const globalSections = await getGlobalSectionsData(previewData) - - if (storeConfig.cms.data) { - const cmsData = JSON.parse(storeConfig.cms.data) - const page = cmsData['search'][0] - - if (page) { - const pageData = await getPage({ - contentType: 'search', - documentId: page.documentId, - versionId: page.versionId, - }) - - return { - props: { page: pageData, globalSections, searchTerm }, - } - } - } - - const page = await getPage({ - ...(previewData?.contentType === 'search' ? previewData : null), - contentType: 'search', - }) - - res.setHeader( - 'Cache-Control', - 'public, s-maxage=300, stale-while-revalidate=31536000' - ) // 5 minutes of fresh content and 1 year of stale content - - return { - props: { - page, - globalSections, - searchTerm, - }, - } -} -` - -const GET_STATIC_PROPS_REGEX = /export const getStaticProps: GetStaticProps<[\s\S]*?>\s*= async \(context\) => \{[\s\S]*?\}/ function enableSearchSSR(basePath: string) { @@ -553,19 +503,12 @@ function enableSearchSSR(basePath: string) { } const { tmpDir } = withBasePath(basePath) - const searchPagePath = path.join(tmpDir, 'src', 'pages', 's.tsx') - const searchPageData = String(readFileSync(searchPagePath)) - let searchPageWithSSR = searchPageData.replace( - GET_STATIC_PROPS_REGEX, - GET_SERVER_SIDE_PROPS - ) - searchPageWithSSR.replace("import type { GetStaticProps } from 'next'", "import type { GetServerSideProps } from 'next'") + const searchPageWithSSR = searchPageData.replaceAll('getStaticProps', 'getServerSideProps') writeFileSync(searchPagePath, searchPageWithSSR) - } export async function generate(options: GenerateOptions) { diff --git a/packages/core/src/experimental/searchServerSideFunctions/getServerSideProps.ts b/packages/core/src/experimental/searchServerSideFunctions/getServerSideProps.ts new file mode 100644 index 0000000000..46036c1009 --- /dev/null +++ b/packages/core/src/experimental/searchServerSideFunctions/getServerSideProps.ts @@ -0,0 +1,51 @@ +import { GetServerSideProps } from 'next' +import { SearchPageProps } from './getStaticProps' + +import { getGlobalSectionsData } from 'src/components/cms/GlobalSections' +import { SearchContentType, getPage } from 'src/server/cms' +import { Locator } from '@vtex/client-cms' +import storeConfig from 'discovery.config' + +export const getServerSideProps: GetServerSideProps< + SearchPageProps, + Record, + Locator +> = async (context) => { + const { previewData, query, res } = context + const searchTerm = (query.q as string)?.split('+').join(' ') + + const globalSections = await getGlobalSectionsData(previewData) + + if (storeConfig.cms.data) { + const cmsData = JSON.parse(storeConfig.cms.data) + const page = cmsData['search'][0] + if (page) { + const pageData = await getPage({ + contentType: 'search', + documentId: page.documentId, + versionId: page.versionId, + }) + return { + props: { page: pageData, globalSections, searchTerm }, + } + } + } + + const page = await getPage({ + ...(previewData?.contentType === 'search' ? previewData : null), + contentType: 'search', + }) + + res.setHeader( + 'Cache-Control', + 'public, s-maxage=300, stale-while-revalidate=31536000' + ) // 5 minutes of fresh content and 1 year of stale content + + return { + props: { + page, + globalSections, + searchTerm, + }, + } +} diff --git a/packages/core/src/experimental/searchServerSideFunctions/getStaticProps.ts b/packages/core/src/experimental/searchServerSideFunctions/getStaticProps.ts new file mode 100644 index 0000000000..4d0c6405c5 --- /dev/null +++ b/packages/core/src/experimental/searchServerSideFunctions/getStaticProps.ts @@ -0,0 +1,53 @@ +import { GetStaticProps } from 'next' +import { + getGlobalSectionsData, + GlobalSectionsData, +} from 'src/components/cms/GlobalSections' +import { SearchContentType, getPage } from 'src/server/cms' +import { Locator } from '@vtex/client-cms' +import storeConfig from 'discovery.config' + +export type SearchPageProps = { + page: SearchContentType + globalSections: GlobalSectionsData + searchTerm?: string +} + +export const getStaticProps: GetStaticProps< + SearchPageProps, + Record, + Locator +> = async (context) => { + const { previewData } = context + + const globalSections = await getGlobalSectionsData(previewData) + + if (storeConfig.cms.data) { + const cmsData = JSON.parse(storeConfig.cms.data) + const page = cmsData['search'][0] + + if (page) { + const pageData = await getPage({ + contentType: 'search', + documentId: page.documentId, + versionId: page.versionId, + }) + + return { + props: { page: pageData, globalSections }, + } + } + } + + const page = await getPage({ + ...(previewData?.contentType === 'search' ? previewData : null), + contentType: 'search', + }) + + return { + props: { + page, + globalSections, + }, + } +} diff --git a/packages/core/src/experimental/searchServerSideFunctions/index.ts b/packages/core/src/experimental/searchServerSideFunctions/index.ts new file mode 100644 index 0000000000..962debee2b --- /dev/null +++ b/packages/core/src/experimental/searchServerSideFunctions/index.ts @@ -0,0 +1,2 @@ +export * from './getServerSideProps' +export * from './getStaticProps' diff --git a/packages/core/src/pages/s.tsx b/packages/core/src/pages/s.tsx index db952d609c..99e4d15e79 100644 --- a/packages/core/src/pages/s.tsx +++ b/packages/core/src/pages/s.tsx @@ -1,4 +1,3 @@ -import type { GetStaticProps } from 'next' import { NextSeo } from 'next-seo' import { useRouter } from 'next/router' import { useMemo } from 'react' @@ -14,20 +13,13 @@ import { SROnly as UISROnly } from '@faststore/ui' import { ITEMS_PER_PAGE } from 'src/constants' import { useApplySearchState } from 'src/sdk/search/state' -import { Locator } from '@vtex/client-cms' import storeConfig from 'discovery.config' -import { - getGlobalSectionsData, - GlobalSectionsData, -} from 'src/components/cms/GlobalSections' -import { SearchWrapper } from 'src/components/templates/SearchPage' -import { getPage, SearchContentType } from 'src/server/cms' -type Props = { - page: SearchContentType - globalSections: GlobalSectionsData - searchTerm?: string -} +import { SearchWrapper } from 'src/components/templates/SearchPage' +import { + getStaticProps, + SearchPageProps, +} from 'src/experimental/searchServerSideFunctions' export interface SearchPageContextType { title: string @@ -55,7 +47,11 @@ const useSearchParams = ({ }, [asPath, defaultSort]) } -function Page({ page: searchContentType, globalSections, searchTerm }: Props) { +function Page({ + page: searchContentType, + globalSections, + searchTerm, +}: SearchPageProps) { const { settings } = searchContentType const applySearchState = useApplySearchState() const searchParams = useSearchParams({ @@ -129,43 +125,6 @@ function Page({ page: searchContentType, globalSections, searchTerm }: Props) { ) } -export const getStaticProps: GetStaticProps< - Props, - Record, - Locator -> = async (context) => { - const { previewData } = context - - const globalSections = await getGlobalSectionsData(previewData) - - if (storeConfig.cms.data) { - const cmsData = JSON.parse(storeConfig.cms.data) - const page = cmsData['search'][0] - - if (page) { - const pageData = await getPage({ - contentType: 'search', - documentId: page.documentId, - versionId: page.versionId, - }) - - return { - props: { page: pageData, globalSections }, - } - } - } - - const page = await getPage({ - ...(previewData?.contentType === 'search' ? previewData : null), - contentType: 'search', - }) - - return { - props: { - page, - globalSections, - }, - } -} +export { getStaticProps } export default Page From e5b821251aa8b36670ffe06f44ce069243402e55 Mon Sep 17 00:00:00 2001 From: Pedro Soares Date: Tue, 28 Jan 2025 10:27:17 -0300 Subject: [PATCH 6/8] feat: Refactor the code --- packages/core/discovery.config.default.js | 1 - .../getServerSideProps.ts | 2 +- .../getStaticProps.ts | 4 + packages/core/src/pages/s.tsx | 78 ++++++++++++------- 4 files changed, 54 insertions(+), 31 deletions(-) diff --git a/packages/core/discovery.config.default.js b/packages/core/discovery.config.default.js index 538b0c6b64..80019b6fda 100644 --- a/packages/core/discovery.config.default.js +++ b/packages/core/discovery.config.default.js @@ -11,7 +11,6 @@ module.exports = { search: { titleTemplate: '%s: Search results title', descriptionTemplate: '%s: Search results description', - title: 'Search Results', }, }, diff --git a/packages/core/src/experimental/searchServerSideFunctions/getServerSideProps.ts b/packages/core/src/experimental/searchServerSideFunctions/getServerSideProps.ts index 46036c1009..40c652fa2a 100644 --- a/packages/core/src/experimental/searchServerSideFunctions/getServerSideProps.ts +++ b/packages/core/src/experimental/searchServerSideFunctions/getServerSideProps.ts @@ -38,7 +38,7 @@ export const getServerSideProps: GetServerSideProps< res.setHeader( 'Cache-Control', - 'public, s-maxage=300, stale-while-revalidate=31536000' + 'public, s-maxage=300, stale-while-revalidate=31536000, stale-if-error=31536000' ) // 5 minutes of fresh content and 1 year of stale content return { diff --git a/packages/core/src/experimental/searchServerSideFunctions/getStaticProps.ts b/packages/core/src/experimental/searchServerSideFunctions/getStaticProps.ts index 4d0c6405c5..5e6a805377 100644 --- a/packages/core/src/experimental/searchServerSideFunctions/getStaticProps.ts +++ b/packages/core/src/experimental/searchServerSideFunctions/getStaticProps.ts @@ -13,6 +13,10 @@ export type SearchPageProps = { searchTerm?: string } +/* + Depending on the value of the storeConfig.experimental.enableSearchSSR flag, the function used will be getServerSideProps (./getServerSideProps). + Our CLI that does this process of converting from getStaticProps to getServerSideProps. +*/ export const getStaticProps: GetStaticProps< SearchPageProps, Record, diff --git a/packages/core/src/pages/s.tsx b/packages/core/src/pages/s.tsx index 99e4d15e79..3e5157b43d 100644 --- a/packages/core/src/pages/s.tsx +++ b/packages/core/src/pages/s.tsx @@ -47,6 +47,50 @@ const useSearchParams = ({ }, [asPath, defaultSort]) } +type StoreConfig = typeof storeConfig + +function generateSEOData(storeConfig: StoreConfig, searchTerm?: string) { + const { search: searchSeo, ...seo } = storeConfig.seo + + const isSSREnabled = storeConfig.experimental.enableSearchSSR + + // default behavior without SSR + if (!isSSREnabled) { + return { + title: seo.title, + description: seo.description, + titleTemplate: seo.titleTemplate, + openGraph: { + type: 'website', + title: seo.title, + description: seo.description, + }, + } + } + + const title = searchTerm ?? 'Search Results' + const titleTemplate = searchSeo?.titleTemplate ?? seo.titleTemplate + const description = searchSeo?.descriptionTemplate + ? searchSeo.descriptionTemplate.replace(/%s/g, () => searchTerm) + : seo.description + + const canonical = searchTerm + ? `${storeConfig.storeUrl}?s=${searchTerm}` + : undefined + + return { + title, + description, + titleTemplate, + canonical, + openGraph: { + type: 'website', + title: title, + description: description, + }, + } +} + function Page({ page: searchContentType, globalSections, @@ -58,26 +102,13 @@ function Page({ sort: settings?.productGallery?.sortBySelection as SearchState['sort'], }) - const { description, titleTemplate, search } = storeConfig.seo const itemsPerPage = settings?.productGallery?.itemsPerPage ?? ITEMS_PER_PAGE if (!searchParams) { return null } - const title = search?.title ?? 'Search Results' - const currentTitleTemplate = search?.titleTemplate ?? titleTemplate - - const isSSREnabled = storeConfig.experimental.enableSearchSSR - const currentSearchTerm = isSSREnabled ? searchTerm : searchParams.term - const currentTitle = isSSREnabled ? searchTerm : title - const currentDescription = isSSREnabled - ? search.descriptionTemplate.replace(/%s/g, () => searchTerm) - : description - - const canonical = currentSearchTerm - ? `${storeConfig.storeUrl}?s=${currentSearchTerm}` - : undefined + const seoData = generateSEOData(storeConfig, searchTerm) return ( {/* SEO */} - + - + {/* WARNING: Do not import or render components from any @@ -116,8 +136,8 @@ function Page({ itemsPerPage={itemsPerPage} searchContentType={searchContentType} serverData={{ - title, - searchTerm: currentSearchTerm ?? undefined, + title: seoData.title, + searchTerm: searchParams.term ?? undefined, }} globalSections={globalSections.sections} /> From 2ed480c1ada4ee6ffd71540c8cc98840c97b6974 Mon Sep 17 00:00:00 2001 From: Pedro Soares Date: Tue, 28 Jan 2025 16:49:09 -0300 Subject: [PATCH 7/8] fix: canonical url --- packages/core/src/pages/s.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/pages/s.tsx b/packages/core/src/pages/s.tsx index 3e5157b43d..ce4ddc5767 100644 --- a/packages/core/src/pages/s.tsx +++ b/packages/core/src/pages/s.tsx @@ -75,7 +75,7 @@ function generateSEOData(storeConfig: StoreConfig, searchTerm?: string) { : seo.description const canonical = searchTerm - ? `${storeConfig.storeUrl}?s=${searchTerm}` + ? `${storeConfig.storeUrl}/s?q=${searchTerm}` : undefined return { From bcb892615656e903b807aeb475bd7aa5249a5bf3 Mon Sep 17 00:00:00 2001 From: Pedro Soares Date: Wed, 29 Jan 2025 09:54:15 -0300 Subject: [PATCH 8/8] chore: pr adjusts --- packages/cli/src/utils/generate.ts | 2 -- packages/core/src/pages/s.tsx | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/cli/src/utils/generate.ts b/packages/cli/src/utils/generate.ts index 70a25f9dff..8b7093b75c 100644 --- a/packages/cli/src/utils/generate.ts +++ b/packages/cli/src/utils/generate.ts @@ -489,8 +489,6 @@ function enableRedirectsMiddleware(basePath: string) { } } - - function enableSearchSSR(basePath: string) { const storeConfigPath = getCurrentUserStoreConfigFile(basePath) diff --git a/packages/core/src/pages/s.tsx b/packages/core/src/pages/s.tsx index ce4ddc5767..2e01d8f1dc 100644 --- a/packages/core/src/pages/s.tsx +++ b/packages/core/src/pages/s.tsx @@ -137,7 +137,7 @@ function Page({ searchContentType={searchContentType} serverData={{ title: seoData.title, - searchTerm: searchParams.term ?? undefined, + searchTerm: searchTerm ?? searchParams.term ?? undefined, }} globalSections={globalSections.sections} />