Skip to content

Commit c09f9b5

Browse files
authored
Server rendering for homepage, units and topics listing pages (#1822)
* Warn on API calls during initial render not prefetched * Full prefetch for homepage (commented) * Prefetch utility * Check for queries prefetched that are not needed during render and warn * No need to stringify * Replace useQuery overrides with decoupled cache check (wip) * Observer count for unnecessary prefetch warnings * Remove useQuery override * Test prefetch warnings * Remove inadvertent/unnecessary diff * Remove comments * Prefetch homepage. Invalidate learning resource cache items * Remove comment * Update comment * Temp remove featured resource list shuffle * Remove unused * Prefetch calls * Prefetch topics page * Rename key factory re-exports * Units page prefetch * Single request for all unit channel details * Update unit listing page tests * Page arg types * Optional route params * Remove comment * Remove unused * Remove comment
1 parent 97ff40c commit c09f9b5

File tree

29 files changed

+280
-173
lines changed

29 files changed

+280
-173
lines changed

frontends/api/src/hooks/channels/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,5 @@ export {
5555
useChannelsList,
5656
useChannelPartialUpdate,
5757
useChannelCounts,
58-
channels as channelsKeyFactory,
58+
channels,
5959
}

frontends/api/src/hooks/learningResources/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,5 +531,5 @@ export {
531531
useListItemMove,
532532
usePlatformsList,
533533
useSchoolsList,
534-
learningResources as learningResourcesKeyFactory,
534+
learningResources,
535535
}

frontends/api/src/hooks/learningResources/keyFactory.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ import type {
3333

3434
import { createQueryKeys } from "@lukemorales/query-key-factory"
3535

36+
/* TODO we can add this back in once resource user list membership is implemented in the front end
37+
* Currently we fetch on the server for public resources and then refetch on the client for the
38+
* user lists parents. Randomizing therefore causes a content flicker as the client loaded
39+
* sequence replaces the server rendered sequence.
40+
3641
const shuffle = ([...arr]) => {
3742
let m = arr.length
3843
while (m) {
@@ -61,6 +66,7 @@ const randomizeResults = ([...results]) => {
6166
})
6267
return randomizedResults
6368
}
69+
*/
6470

6571
const learningResources = createQueryKeys("learningResources", {
6672
detail: (id: number) => ({
@@ -81,7 +87,7 @@ const learningResources = createQueryKeys("learningResources", {
8187
queryKey: [params],
8288
queryFn: () => {
8389
return featuredApi.featuredList(params).then((res) => {
84-
res.data.results = randomizeResults(res.data?.results)
90+
// res.data.results = randomizeResults(res.data?.results)
8591
return res.data
8692
})
8793
},

frontends/api/src/hooks/newsEvents/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@ export {
1919
useNewsEventsList,
2020
useNewsEventsDetail,
2121
NewsEventsListFeedTypeEnum,
22-
newsEvents as newsEventsKeyFactory,
22+
newsEvents,
2323
}

frontends/api/src/hooks/testimonials/index.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,4 @@ const useTestimonialDetail = (id: number | undefined) => {
2323
})
2424
}
2525

26-
export {
27-
useTestimonialDetail,
28-
useTestimonialList,
29-
testimonials as testimonialsKeyFactory,
30-
}
26+
export { useTestimonialDetail, useTestimonialList, testimonials }

frontends/api/src/ssr/prefetch.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
import { QueryClient, dehydrate } from "@tanstack/react-query"
22
import type { Query } from "@tanstack/react-query"
33

4-
// Utility to avoid repetition in server components
5-
export const prefetch = async (queries: (Query | unknown)[]) => {
6-
const queryClient = new QueryClient()
4+
/* Utility to avoid repetition in server components
5+
* Optionally pass the queryClient returned from a previous prefetch
6+
* where queries are dependent on previous results
7+
*/
8+
export const prefetch = async (
9+
queries: (Query | unknown)[],
10+
queryClient?: QueryClient,
11+
) => {
12+
queryClient = queryClient || new QueryClient()
713

814
await Promise.all(
915
queries.map((query) => queryClient.prefetchQuery(query as Query)),
1016
)
1117

12-
return dehydrate(queryClient)
18+
return { dehydratedState: dehydrate(queryClient), queryClient }
1319
}

frontends/api/src/ssr/usePrefetchWarnings.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { usePrefetchWarnings } from "./usePrefetchWarnings"
44
import { setupReactQueryTest } from "../hooks/test-utils"
55
import { urls, factories, setMockResponse } from "../test-utils"
66
import {
7-
learningResourcesKeyFactory,
7+
learningResources,
88
useLearningResourcesDetail,
99
} from "../hooks/learningResources"
1010

@@ -45,7 +45,7 @@ describe("SSR prefetch warnings", () => {
4545
expect.objectContaining({
4646
disabled: false,
4747
initialStatus: "loading",
48-
key: learningResourcesKeyFactory.detail(1).queryKey,
48+
key: learningResources.detail(1).queryKey,
4949
observerCount: 1,
5050
}),
5151
],
@@ -65,7 +65,7 @@ describe("SSR prefetch warnings", () => {
6565
wrapper,
6666
initialProps: {
6767
queryClient,
68-
exemptions: [learningResourcesKeyFactory.detail(1).queryKey],
68+
exemptions: [learningResources.detail(1).queryKey],
6969
},
7070
})
7171

@@ -83,7 +83,7 @@ describe("SSR prefetch warnings", () => {
8383
const { unmount } = renderHook(
8484
() =>
8585
useQuery({
86-
...learningResourcesKeyFactory.detail(1),
86+
...learningResources.detail(1),
8787
initialData: data,
8888
}),
8989
{ wrapper },
@@ -105,9 +105,9 @@ describe("SSR prefetch warnings", () => {
105105
[
106106
{
107107
disabled: false,
108-
hash: JSON.stringify(learningResourcesKeyFactory.detail(1).queryKey),
108+
hash: JSON.stringify(learningResources.detail(1).queryKey),
109109
initialStatus: "success",
110-
key: learningResourcesKeyFactory.detail(1).queryKey,
110+
key: learningResources.detail(1).queryKey,
111111
observerCount: 0,
112112
status: "success",
113113
},

frontends/api/src/ssr/usePrefetchWarnings.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ export const usePrefetchWarnings = ({
4545
*/
4646
useEffect(
4747
() => {
48+
/* Invalidate all learning resource queries so they are re-fetched in the client
49+
* for session specific data (user list memberships).
50+
* This is interim, until the memberships endpoint is implemented in the frontend
51+
* TODO remove once complete (see https://github.com/mitodl/hq/issues/5159)
52+
*/
53+
queryClient.invalidateQueries(["learningResources"])
54+
4855
if (process.env.NODE_ENV === "production") {
4956
return
5057
}

frontends/api/src/test-utils/factories/channels.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ const _channelShared = (): Partial<Omit<Channel, "channel_type">> => {
148148
key: faker.lorem.slug(),
149149
value: faker.lorem.slug(),
150150
}),
151+
channel_url: `${faker.internet.url({ appendSlash: false })}${faker.system.directoryPath()}`,
151152
}
152153
}
153154

frontends/api/src/test-utils/urls.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import type {
99
NewsEventsApiNewsEventsListRequest,
1010
TestimonialsApi,
11+
ChannelsApi,
1112
} from "../generated/v0"
1213
import type {
1314
LearningResourcesApi as LRApi,
@@ -179,6 +180,8 @@ const channels = {
179180
details: (channelType: string, name: string) =>
180181
`${API_BASE_URL}/api/v0/channels/type/${channelType}/${name}/`,
181182
patch: (id: number) => `${API_BASE_URL}/api/v0/channels/${id}/`,
183+
list: (params?: Paramsv0<ChannelsApi, "channelsList">) =>
184+
`${API_BASE_URL}/api/v0/channels/${query(params)}`,
182185
}
183186

184187
const widgetLists = {

0 commit comments

Comments
 (0)