Skip to content

Commit

Permalink
Improve landing page load time (#1124)
Browse files Browse the repository at this point in the history
* refactor: optimizing landing page. set revalidate at `fetch` call
* refactor: use experimental apollo client for server component
  • Loading branch information
vnugent authored Apr 30, 2024
1 parent 3d88dc4 commit 27401ed
Show file tree
Hide file tree
Showing 16 changed files with 152 additions and 35 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"dependencies": {
"@algolia/autocomplete-js": "1.7.1",
"@algolia/autocomplete-theme-classic": "1.7.1",
"@apollo/client": "^3.7.16",
"@apollo/client": "^3.10.1",
"@apollo/experimental-nextjs-app-support": "^0.10.0",
"@dnd-kit/core": "^6.1.0",
"@dnd-kit/sortable": "^8.0.0",
"@dnd-kit/utilities": "^3.2.2",
Expand Down
2 changes: 1 addition & 1 deletion src/app/(default)/area/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { AuthorMetadata, OrganizationType } from '@/js/types'
/**
* Page cache settings
*/
export const revalidate = 86400 // 24 hours
export const revalidate = 300 // 5 mins
export const fetchCache = 'force-no-store' // opt out of Nextjs version of 'fetch'

interface PageSlugType {
Expand Down
4 changes: 2 additions & 2 deletions src/app/(default)/components/RecentTags.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { RecentImageCard } from '@/components/home/RecentMediaCard'
import { getMediaForFeed } from '@/js/graphql/api'
import { getMediaForFeedSC } from '@/js/graphql/gql/serverApi'

/**
* Horizontal gallery of recent images with tags
*/
export const RecentTags: React.FC = async () => {
const recentTagsByUsers = await getMediaForFeed(20, 4)
const recentTagsByUsers = await getMediaForFeedSC(20, 4)
const testAreaIds = Array.from(new Set((process.env.NEXT_PUBLIC_TEST_AREA_IDS ?? '').split(',')))
const mediaWithTags = recentTagsByUsers.flatMap(entry => entry.mediaWithTags)

Expand Down
2 changes: 1 addition & 1 deletion src/app/(default)/components/Volunteers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ interface GithubProfile {
* managed by all-contributors bot.
*/
export const Volunteers: React.FC = async () => {
const res = await fetch(url, { cache: 'no-store' })
const res = await fetch(url, { next: { revalidate: 84600 } })
const { contributors }: { contributors: GithubProfile[] } = await res.json()
return (
<SectionContainer
Expand Down
2 changes: 1 addition & 1 deletion src/app/(default)/edit/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const metadata: Metadata = {
description: 'Share your climbing adventure photos and contribute to the climbing route catalog.'
}

export const revalidate = 3600
export const revalidate = 600

export default async function Page (): Promise<ReactElement> {
const history = await getChangeHistoryServerSide()
Expand Down
5 changes: 3 additions & 2 deletions src/app/(default)/header.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import clx from 'classnames'
import Link from 'next/link'

import OpenBetaLogo from '@/assets/brand/openbeta-logo'
import { DesktopHeader } from './components/DesktopHeader'
Expand Down Expand Up @@ -26,9 +27,9 @@ export enum LogoSize {
*/
export const Logo: React.FC<{ size?: LogoSize, className?: string, withText?: boolean }> = ({ size = LogoSize.sm, className, withText = false }) => {
return (
<a href='/' className='flex items-center gap-2'>
<Link href='/' className='flex items-center gap-2'>
<OpenBetaLogo className={clx(size, className)} />
{withText && <span className='font-bold text-lg tracking-tight'>OpenBeta</span>}
</a>
</Link>
)
}
5 changes: 1 addition & 4 deletions src/app/(default)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ import { InternationalToC } from './components/InternationalToC'
import { Volunteers } from './components/Volunteers'
import { RecentContributionsMap } from './components/recent/RecentContributionsMap'

/**
* Cache duration in seconds
*/
export const dynamic = 'force-dynamic'
export const revalidate = 3600 // 1 hour

/**
* Root home page
Expand Down
3 changes: 2 additions & 1 deletion src/app/(maps)/components/ProfileMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
'use client'
import Link from 'next/link'
import { SessionProvider } from 'next-auth/react'
import { House } from '@phosphor-icons/react/dist/ssr'
import AuthenticatedProfileNavButton from '@/components/AuthenticatedProfileNavButton'
Expand All @@ -9,7 +10,7 @@ export const ProfileMenu: React.FC = () => {
<SessionProvider>
<div className='absolute right-4 top-4 z-50'>
<nav className='flex items-center gap-2'>
<a className='btn glass' href='/'><House size={18} />Home</a>
<Link className='btn glass' href='/'><House size={18} />Home</Link>
<AuthenticatedProfileNavButton isMobile={false} />
</nav>
</div>
Expand Down
2 changes: 2 additions & 0 deletions src/app/api/updateAreaPage/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export async function GET (request: NextRequest): Promise<any> {
} else {
revalidatePath(`/area/${uuid}`, 'page')
revalidatePath(`/editArea/${uuid}`, 'layout')
revalidatePath('/', 'page')
revalidatePath('/edit', 'page')
return NextResponse.json({ message: 'OK' }, { status: 200 })
}
}
9 changes: 7 additions & 2 deletions src/js/graphql/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ if (openCollectiveApiKey !== '') {
}

export const openCollectiveClient = new ApolloClient({
uri: openCollectiveUri,
cache: new InMemoryCache()
cache: new InMemoryCache(),
link: new HttpLink({
uri: openCollectiveUri,
fetchOptions: {
next: { revalidate: 3600 }
}
})
})
23 changes: 23 additions & 0 deletions src/js/graphql/ServerClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client'
import { registerApolloClient } from '@apollo/experimental-nextjs-app-support/rsc'

const uri: string = process.env.NEXT_PUBLIC_API_SERVER ?? ''

if (uri === '' || uri == null) {
throw new Error('NEXT_PUBLIC_API_SERVER is not set')
}

/**
* Apollo client to be used in server components.
*/
export const { getClient } = registerApolloClient(() => {
return new ApolloClient({
cache: new InMemoryCache(),
link: new HttpLink({
uri,
fetchOptions: {
next: { revalidate: 3600 } // a non-zero value enables 'public, max-age=0, must-revalidate'
}
})
})
})
5 changes: 3 additions & 2 deletions src/js/graphql/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import AwesomeDebouncePromise from 'awesome-debounce-promise'

import { AreaType, ClimbType, TickType, MediaByUsers, CountrySummaryType, MediaWithTags } from '../types'
import { graphqlClient } from './Client'

import { CORE_CRAG_FIELDS, QUERY_CRAGS_WITHIN, QUERY_TICKS_BY_USER_AND_CLIMB, QUERY_TICKS_BY_USER, QUERY_ALL_COUNTRIES } from './gql/fragments'
import { QUERY_MEDIA_FOR_FEED } from './gql/tags'
import { QUERY_USER_MEDIA } from './gql/users'
Expand Down Expand Up @@ -91,8 +92,8 @@ export const getMediaForFeed = async (maxUsers: number, maxFiles: number): Promi
variables: {
maxUsers,
maxFiles
},
fetchPolicy: 'network-only'
}
// fetchPolicy: 'network-only'
})

if (Array.isArray(rs.data?.getMediaForFeed)) {
Expand Down
8 changes: 4 additions & 4 deletions src/js/graphql/contribAPI.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { QUERY_RECENT_CHANGE_HISTORY } from './gql/contribs'
import { graphqlClient } from './Client'
import { getClient } from './ServerClient'
import { ChangesetType } from '../types'

export const getChangeHistoryServerSide = async (): Promise<ChangesetType[]> => {
try {
const rs = await graphqlClient.query<{ getChangeHistory: ChangesetType[] }>({
const rs = await getClient().query<{ getChangeHistory: ChangesetType[] }>({
query: QUERY_RECENT_CHANGE_HISTORY,
fetchPolicy: 'cache-first'
fetchPolicy: 'no-cache'
})

if (Array.isArray(rs.data?.getChangeHistory)) {
return rs.data?.getChangeHistory.slice(0, 50)
return rs.data?.getChangeHistory.slice(0, 20)
}
console.log('WARNING: getChangeHistory() returns non-array data')
return []
Expand Down
5 changes: 3 additions & 2 deletions src/js/graphql/getPopularAreasUSA.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { gql } from '@apollo/client'

import { FRAGMENT_MEDIA_WITH_TAGS } from './gql/tags'
import { graphqlClient } from './Client'
import { getClient } from './ServerClient'

import { AreaType } from '../types'

/**
Expand Down Expand Up @@ -79,7 +80,7 @@ export interface USAToCProps {
}

export const getPopularAreasInUSA = async (): Promise<USAToCProps> => {
const rs = await graphqlClient.query<USAToCProps>({
const rs = await getClient().query<USAToCProps>({
query,
variables: {
filter: {
Expand Down
30 changes: 30 additions & 0 deletions src/js/graphql/gql/serverApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { getClient } from '../ServerClient'
import { MediaByUsers } from '@/js/types'
import { QUERY_MEDIA_FOR_FEED } from './tags'

/**
* Server component API: Get recent media for feed.
* @param maxUsers
* @param maxFiles
*/
export const getMediaForFeedSC = async (maxUsers: number, maxFiles: number): Promise<MediaByUsers[]> => {
try {
const rs = await getClient().query<{ getMediaForFeed: MediaByUsers[] }>({
query: QUERY_MEDIA_FOR_FEED,
variables: {
maxUsers,
maxFiles
},
fetchPolicy: 'cache-first'
})

if (Array.isArray(rs.data?.getMediaForFeed)) {
return rs.data?.getMediaForFeed
}
console.log('WARNING: getMediaForFeed() returns non-array data')
return []
} catch (e) {
console.log('####### getMediaForFeed() error', e)
}
return []
}
79 changes: 67 additions & 12 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -60,25 +60,41 @@
"@jridgewell/gen-mapping" "^0.3.0"
"@jridgewell/trace-mapping" "^0.3.9"

"@apollo/client@^3.7.16":
version "3.8.4"
resolved "https://registry.npmjs.org/@apollo/client/-/client-3.8.4.tgz"
integrity sha512-QFXE4ylSHUa6LgYoOGsPysJCm4YJOOM1NwHyF6msZdZXIerqUVpLvxQOdQEXgS0RWvYiBMC1wGOWKzJKSWBdAg==
"@apollo/[email protected]":
version "0.10.0"
resolved "https://registry.yarnpkg.com/@apollo/client-react-streaming/-/client-react-streaming-0.10.0.tgz#1f9a818c679b41791ca02105f16525c93412994c"
integrity sha512-iZ2jYghRS71xFv6O3Js5Ojrrmk4SnIEKwPRKIswQyAtqjHrfvUTyXCDzxrhPcGQe/y7su/XcE7Xp0kOp7yTnlg==
dependencies:
superjson "^1.12.2 || ^2.0.0"
ts-invariant "^0.10.3"

"@apollo/client@^3.10.1":
version "3.10.1"
resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.10.1.tgz#4c8eec28fcce25b96f27c1f1e443ec5c676e4de0"
integrity sha512-QNacQBZzJla5UQ/LLBXJWM7/1v1C5cfpMQPAFjW4hg4T54wHWbg4Dr+Dp6N+hy/ygu8tepdM+/y/5VFLZhovlQ==
dependencies:
"@graphql-typed-document-node/core" "^3.1.1"
"@wry/context" "^0.7.3"
"@wry/caches" "^1.0.0"
"@wry/equality" "^0.5.6"
"@wry/trie" "^0.4.3"
"@wry/trie" "^0.5.0"
graphql-tag "^2.12.6"
hoist-non-react-statics "^3.3.2"
optimism "^0.17.5"
optimism "^0.18.0"
prop-types "^15.7.2"
rehackt "^0.1.0"
response-iterator "^0.2.6"
symbol-observable "^4.0.0"
ts-invariant "^0.10.3"
tslib "^2.3.0"
zen-observable-ts "^1.2.5"

"@apollo/experimental-nextjs-app-support@^0.10.0":
version "0.10.0"
resolved "https://registry.yarnpkg.com/@apollo/experimental-nextjs-app-support/-/experimental-nextjs-app-support-0.10.0.tgz#2fe52e6bc18de87c17bfc2bc78ec63acf8260c8f"
integrity sha512-S3mfZRnAAAaKwA8RNckS4TWYLX5utpmRTwG3WGFtpooYx8QQG8xft0p0a9eTQ53Jrw3nSMJc/wOOsT/5noMCQg==
dependencies:
"@apollo/client-react-streaming" "0.10.0"

"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13":
version "7.22.13"
resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz"
Expand Down Expand Up @@ -3017,7 +3033,14 @@
resolved "https://registry.yarnpkg.com/@vercel/edge/-/edge-1.1.1.tgz#9b2fc0081dfe95db8b4c3598275721b1ad85e43f"
integrity sha512-NtKiIbn9Cq6HWGy+qRudz28mz5nxfOJWls5Pnckjw1yCfSX8rhXdvY/il3Sy3Zd5n/sKCM2h7VSCCpJF/oaDrQ==

"@wry/context@^0.7.0", "@wry/context@^0.7.3":
"@wry/caches@^1.0.0":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@wry/caches/-/caches-1.0.1.tgz#8641fd3b6e09230b86ce8b93558d44cf1ece7e52"
integrity sha512-bXuaUNLVVkD20wcGBWRyo7j9N3TxePEWFZj2Y+r9OoUzfqmavM84+mFykRicNsBqatba5JLay1t48wxaXaWnlA==
dependencies:
tslib "^2.3.0"

"@wry/context@^0.7.0":
version "0.7.3"
resolved "https://registry.npmjs.org/@wry/context/-/context-0.7.3.tgz"
integrity sha512-Nl8WTesHp89RF803Se9X3IiHjdmLBrIvPMaJkl+rKVJAYyPsz1TEUbu89943HpvujtSJgDUx9W4vZw3K1Mr3sA==
Expand All @@ -3038,6 +3061,13 @@
dependencies:
tslib "^2.3.0"

"@wry/trie@^0.5.0":
version "0.5.0"
resolved "https://registry.yarnpkg.com/@wry/trie/-/trie-0.5.0.tgz#11e783f3a53f6e4cd1d42d2d1323f5bc3fa99c94"
integrity sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA==
dependencies:
tslib "^2.3.0"

"@xobotyi/scrollbar-width@^1.9.5":
version "1.9.5"
resolved "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz"
Expand Down Expand Up @@ -3849,6 +3879,13 @@ cookiejar@^2.1.3:
resolved "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz"
integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==

copy-anything@^3.0.2:
version "3.0.5"
resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-3.0.5.tgz#2d92dce8c498f790fa7ad16b01a1ae5a45b020a0"
integrity sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==
dependencies:
is-what "^4.1.8"

copy-to-clipboard@^3.3.1:
version "3.3.3"
resolved "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz"
Expand Down Expand Up @@ -5847,6 +5884,11 @@ is-weakset@^2.0.1:
call-bind "^1.0.2"
get-intrinsic "^1.1.1"

is-what@^4.1.8:
version "4.1.16"
resolved "https://registry.yarnpkg.com/is-what/-/is-what-4.1.16.tgz#1ad860a19da8b4895ad5495da3182ce2acdd7a6f"
integrity sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==

isarray@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz"
Expand Down Expand Up @@ -7409,11 +7451,12 @@ openid-client@^5.4.0:
object-hash "^2.2.0"
oidc-token-hash "^5.0.3"

optimism@^0.17.5:
version "0.17.5"
resolved "https://registry.npmjs.org/optimism/-/optimism-0.17.5.tgz"
integrity sha512-TEcp8ZwK1RczmvMnvktxHSF2tKgMWjJ71xEFGX5ApLh67VsMSTy1ZUlipJw8W+KaqgOmQ+4pqwkeivY89j+4Vw==
optimism@^0.18.0:
version "0.18.0"
resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.18.0.tgz#e7bb38b24715f3fdad8a9a7fc18e999144bbfa63"
integrity sha512-tGn8+REwLRNFnb9WmcY5IfpOqeX2kpaYJ1s6Ae3mn12AeydLkR3j+jSCmVQFoXqU8D41PAJ1RG1rCRNWmNZVmQ==
dependencies:
"@wry/caches" "^1.0.0"
"@wry/context" "^0.7.0"
"@wry/trie" "^0.4.3"
tslib "^2.3.0"
Expand Down Expand Up @@ -8255,6 +8298,11 @@ regjsparser@^0.9.1:
dependencies:
jsesc "~0.5.0"

rehackt@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/rehackt/-/rehackt-0.1.0.tgz#a7c5e289c87345f70da8728a7eb878e5d03c696b"
integrity sha512-7kRDOuLHB87D/JESKxQoRwv4DzbIdwkAGQ7p6QKGdVlY1IZheUnVhlk/4UZlNUVxdAXpyxikE3URsG067ybVzw==

remark-parse@^11.0.0:
version "11.0.0"
resolved "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz"
Expand Down Expand Up @@ -8876,6 +8924,13 @@ supercluster@^8.0.0, supercluster@^8.0.1:
dependencies:
kdbush "^4.0.2"

"superjson@^1.12.2 || ^2.0.0":
version "2.2.1"
resolved "https://registry.yarnpkg.com/superjson/-/superjson-2.2.1.tgz#9377a7fa80fedb10c851c9dbffd942d4bcf79733"
integrity sha512-8iGv75BYOa0xRJHK5vRLEjE2H/i4lulTjzpUXic3Eg8akftYjkmQDa8JARQ42rlczXyFR3IeRoeFCc7RxHsYZA==
dependencies:
copy-anything "^3.0.2"

supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz"
Expand Down

0 comments on commit 27401ed

Please sign in to comment.