From 387657ba47412435ffb96da611d39a4ab9652841 Mon Sep 17 00:00:00 2001 From: rinaldo stevenazzi Date: Wed, 29 Nov 2023 16:42:56 +0100 Subject: [PATCH 1/8] test invalidate cache --- src/app/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index ec30204..b94badf 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -21,8 +21,7 @@ try { const getHigherScores = async () => { try { const response = await fetch(`${server}/api/higher-scores`, { - method: 'GET', - cache: 'no-store', + next: { revalidate: 0 }, }) if (!response) { @@ -31,6 +30,7 @@ const getHigherScores = async () => { }) } const result = await response.json() + console.log('getHigherScores - result', result) const { scores } = result return Scores.getScoresParsedAndOrdered(scores) } catch { From 24c5059e66e661b634fc10202fcc262493193ad7 Mon Sep 17 00:00:00 2001 From: rinaldo stevenazzi Date: Wed, 29 Nov 2023 17:09:42 +0100 Subject: [PATCH 2/8] add no store option --- src/app/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index b94badf..c481f8c 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -21,7 +21,7 @@ try { const getHigherScores = async () => { try { const response = await fetch(`${server}/api/higher-scores`, { - next: { revalidate: 0 }, + cache: 'no-store', }) if (!response) { From 0bfe0260d4bb118652e36d21f6cae95b454fa9d5 Mon Sep 17 00:00:00 2001 From: rinaldo stevenazzi Date: Wed, 29 Nov 2023 17:32:54 +0100 Subject: [PATCH 3/8] add export variable to invalidate the cache on server component --- src/app/page.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index c481f8c..1d2c9f5 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,10 +1,13 @@ +// https://nextjs.org/docs/app/building-your-application/caching#segment-config-options +export const dynamic = 'force-dynamic' +export const revalidate = 0 + +import { cookies } from 'next/headers' import { Box, CircularProgress } from '@mui/material' import { Home } from '@/components/home' -import { ScoreList } from '@/components/score-list' import { Scores } from '@/services/scores' import { APIError } from '@/utils/errors' -import { cookies } from 'next/headers' import { PUZZLE_COOKIE } from '@/constants' let server = 'http://localhost:3000' From cf8d8725fe8a8f3720e01a1c2e701fb76f14f5dc Mon Sep 17 00:00:00 2001 From: rinaldo stevenazzi Date: Thu, 30 Nov 2023 14:15:08 +0100 Subject: [PATCH 4/8] add fix to get server url using header --- README.md | 6 +++++ src/app/api/higher-scores/route.ts | 2 ++ src/app/page.tsx | 41 +++++++++++++++++++---------- src/components/score-list/index.tsx | 23 +++++++++++++--- src/middleware.ts | 9 +++++++ 5 files changed, 63 insertions(+), 18 deletions(-) create mode 100644 src/middleware.ts diff --git a/README.md b/README.md index 1cfbf37..2ece35e 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,12 @@ Main packages : Nextjs App Router project structure based +## Subjects + +- Server side cache invalidation : + - https://galadrim.fr/blog/nextjs-app-router-le-cache-et-ses-dangers + - https://www.answeroverflow.com/m/1103789268679282709 + ## Links - Nextjs tutorial base : https://nextjs.org/learn/basics/navigate-between-pages/client-side diff --git a/src/app/api/higher-scores/route.ts b/src/app/api/higher-scores/route.ts index 5322e61..17e213d 100644 --- a/src/app/api/higher-scores/route.ts +++ b/src/app/api/higher-scores/route.ts @@ -23,6 +23,8 @@ export async function GET() { const scoresOrdered = Scores.getScoresParsedAndOrdered(scoresBase).slice(0, NUMITEMS) const scores = await addUserNameToArrayById(scoresOrdered) + // console.log('GET route - result -->', scores) + if (!scores) { throw new APIError('Find userName by score request failed', { cause: { api: 'Higher score GET', values: 'scores' }, diff --git a/src/app/page.tsx b/src/app/page.tsx index 1d2c9f5..d25a97b 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -2,7 +2,7 @@ export const dynamic = 'force-dynamic' export const revalidate = 0 -import { cookies } from 'next/headers' +import { cookies, headers } from 'next/headers' import { Box, CircularProgress } from '@mui/material' import { Home } from '@/components/home' @@ -10,20 +10,29 @@ import { Scores } from '@/services/scores' import { APIError } from '@/utils/errors' import { PUZZLE_COOKIE } from '@/constants' -let server = 'http://localhost:3000' -try { - const env = process.env.NODE_ENV +// let server = 'http://localhost:3000' +// try { +// const env = process.env.NODE_ENV - if (env == 'production') { - server = 'https://speed-puzzle-kz08m3nxu-001-817d24a7.vercel.app/' - } -} catch (error) { - console.log('ENVIRONEMENT VARIABLE - ERROR', error) -} +// if (env == 'production') { +// server = 'https://speed-puzzle-kz08m3nxu-001-817d24a7.vercel.app/' +// server = 'https://speed-puzzle-git-feature-cache-001-817d24a7.vercel.app/' +// } +// } catch (error) { +// console.log('ENVIRONEMENT VARIABLE - ERROR', error) +// } -const getHigherScores = async () => { +const { signal } = new AbortController() + +const getHigherScores = async (server: string | null) => { try { - const response = await fetch(`${server}/api/higher-scores`, { + if (!server) { + throw new APIError('server url is invalid', { + cause: { api: 'Higher score GET', values: 'scores' }, + }) + } + const response = await fetch(`${server}api/higher-scores`, { + signal, cache: 'no-store', }) @@ -33,7 +42,7 @@ const getHigherScores = async () => { }) } const result = await response.json() - console.log('getHigherScores - result', result) + // console.log('getHigherScores - result', result) const { scores } = result return Scores.getScoresParsedAndOrdered(scores) } catch { @@ -47,9 +56,13 @@ const getPuzzleCookie = () => { } export default async function Page() { - const recentScores = await getHigherScores() + const heads = headers() + const pathname = heads.get('x-url') + const recentScores = await getHigherScores(pathname) const cookie = getPuzzleCookie() + console.log('pathname', pathname) + return ( { sx={{ display: 'flex', flexDirection: 'column', - alignContent: 'center', + width: '100%', }} > {scores.map((item, index) => { @@ -17,12 +17,27 @@ export const ScoreList = ({ scores }: { scores: any[] }) => { sx={{ display: 'flex', flexDirection: 'row', - alignContent: 'flex-start', gap: 10, }} > - {item.userName} - {item.value} + + {item.userName} + + + {item.value} + ) })} diff --git a/src/middleware.ts b/src/middleware.ts new file mode 100644 index 0000000..3ee6d02 --- /dev/null +++ b/src/middleware.ts @@ -0,0 +1,9 @@ +import { NextResponse, type NextRequest } from "next/server"; + +export async function middleware(request: NextRequest) { + return NextResponse.next({ + request: { + headers: new Headers({ "x-url": request.url }), + }, + }); +} \ No newline at end of file From 56bac4a843dd0c3902334be1d95f1358c7a74439 Mon Sep 17 00:00:00 2001 From: rinaldo stevenazzi Date: Thu, 30 Nov 2023 14:34:44 +0100 Subject: [PATCH 5/8] fix score ranking body request --- src/app/api/score-ranking/route.ts | 1 + src/providers/puzzle-provider.tsx | 7 +++---- src/services/server.ts | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/app/api/score-ranking/route.ts b/src/app/api/score-ranking/route.ts index 268bfc4..1d72606 100644 --- a/src/app/api/score-ranking/route.ts +++ b/src/app/api/score-ranking/route.ts @@ -17,6 +17,7 @@ export async function POST(request: NextRequest) { try { const requestData = await request.json() + console.log('requestdata ', requestData) if (!requestData.score) { throw new APIError('Undefined request body informations', { cause: { api: 'Score-ranking POST', values: 'user' }, diff --git a/src/providers/puzzle-provider.tsx b/src/providers/puzzle-provider.tsx index d1b7b3b..f0d954b 100644 --- a/src/providers/puzzle-provider.tsx +++ b/src/providers/puzzle-provider.tsx @@ -94,13 +94,12 @@ export const PuzzleProvider: React.FC = ({ children }) => { async function compareScoreWithDB() { try { - const data = { score: state.result?.value.toString() } - - if (!state.result?.value.toString()) { + if (!state?.result?.value.toString()) { throw new Error() // TODO conitnue to manage the error state } - console.log('compareScoreWithDB - score :', data) + // const data = { score: state?.result?.value.toString() } + // console.log('compareScoreWithDB - score :', data) const response = await API.currentScoreRanking( state.result.value.toString() diff --git a/src/services/server.ts b/src/services/server.ts index d3e4798..46470b7 100644 --- a/src/services/server.ts +++ b/src/services/server.ts @@ -12,13 +12,12 @@ export class API { } static currentScoreRanking = async (score: string) => { - const data = { score } return await fetch('/api/score-ranking', { method: 'POST', headers: { 'Content-Type': 'application/json', }, - body: JSON.stringify(data), + body: JSON.stringify({ score }), }) } From 1acea45f8324c9309d1b284dfda007ff5a7db46a Mon Sep 17 00:00:00 2001 From: rinaldo stevenazzi Date: Thu, 30 Nov 2023 14:49:07 +0100 Subject: [PATCH 6/8] add middleware configuration export --- src/middleware.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/middleware.ts b/src/middleware.ts index 3ee6d02..a74c686 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -1,5 +1,10 @@ import { NextResponse, type NextRequest } from "next/server"; +// https://nextjs.org/docs/app/building-your-application/routing/middleware#matcher +export const config = { + matcher: '/', +} + export async function middleware(request: NextRequest) { return NextResponse.next({ request: { From 901692da43e971737654987c456255c32f4fbdcb Mon Sep 17 00:00:00 2001 From: rinaldo stevenazzi Date: Thu, 30 Nov 2023 15:02:42 +0100 Subject: [PATCH 7/8] refresh router in home component --- src/app/page.tsx | 12 ------------ src/components/home/index.tsx | 4 ++++ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index d25a97b..7755154 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -10,18 +10,6 @@ import { Scores } from '@/services/scores' import { APIError } from '@/utils/errors' import { PUZZLE_COOKIE } from '@/constants' -// let server = 'http://localhost:3000' -// try { -// const env = process.env.NODE_ENV - -// if (env == 'production') { -// server = 'https://speed-puzzle-kz08m3nxu-001-817d24a7.vercel.app/' -// server = 'https://speed-puzzle-git-feature-cache-001-817d24a7.vercel.app/' -// } -// } catch (error) { -// console.log('ENVIRONEMENT VARIABLE - ERROR', error) -// } - const { signal } = new AbortController() const getHigherScores = async (server: string | null) => { diff --git a/src/components/home/index.tsx b/src/components/home/index.tsx index bceec20..e4e2277 100644 --- a/src/components/home/index.tsx +++ b/src/components/home/index.tsx @@ -17,6 +17,10 @@ export const Home = ({ scores, cookie }: { scores: any[]; cookie: any }) => { const router = useRouter() const [userName, setUserNamme] = useState() + useEffect(() => { + router.refresh() + }, [router]) + useEffect(() => { if (cookie) { const cookieValue = JSON.parse(cookie.value) From 361b0d65dae12ab5402ba5653dc9eadca4f616f6 Mon Sep 17 00:00:00 2001 From: rinaldo stevenazzi Date: Thu, 30 Nov 2023 16:30:57 +0100 Subject: [PATCH 8/8] remove api call from page --- src/app/page.tsx | 59 +++++++++++++++++------------------ src/components/home/index.tsx | 28 +++++++++++++++-- 2 files changed, 53 insertions(+), 34 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index 7755154..4a77167 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -12,41 +12,42 @@ import { PUZZLE_COOKIE } from '@/constants' const { signal } = new AbortController() -const getHigherScores = async (server: string | null) => { - try { - if (!server) { - throw new APIError('server url is invalid', { - cause: { api: 'Higher score GET', values: 'scores' }, - }) - } - const response = await fetch(`${server}api/higher-scores`, { - signal, - cache: 'no-store', - }) +// const getHigherScores = async (server: string | null) => { +// try { +// if (!server) { +// throw new APIError('server url is invalid', { +// cause: { api: 'Higher score GET', values: 'scores' }, +// }) +// } +// const response = await fetch(`${server}api/higher-scores`, { +// signal, +// cache: 'no-store', +// next: { revalidate: 0 }, +// }) - if (!response) { - throw new APIError('Higher score request failed', { - cause: { api: 'Higher score GET', values: 'scores' }, - }) - } - const result = await response.json() - // console.log('getHigherScores - result', result) - const { scores } = result - return Scores.getScoresParsedAndOrdered(scores) - } catch { - return [] - } -} +// if (!response) { +// throw new APIError('Higher score request failed', { +// cause: { api: 'Higher score GET', values: 'scores' }, +// }) +// } +// const result = await response.json() +// // console.log('getHigherScores - result', result) +// const { scores } = result +// return Scores.getScoresParsedAndOrdered(scores) +// } catch { +// return [] +// } +// } const getPuzzleCookie = () => { const cookieStore = cookies() return cookieStore.get(PUZZLE_COOKIE) } -export default async function Page() { +export default function Page() { const heads = headers() const pathname = heads.get('x-url') - const recentScores = await getHigherScores(pathname) + // const recentScores = await getHigherScores(pathname) const cookie = getPuzzleCookie() console.log('pathname', pathname) @@ -67,11 +68,7 @@ export default async function Page() { gap: 4, }} > - {recentScores ? ( - - ) : ( - - )} + ) } diff --git a/src/components/home/index.tsx b/src/components/home/index.tsx index e4e2277..b13bfa2 100644 --- a/src/components/home/index.tsx +++ b/src/components/home/index.tsx @@ -7,19 +7,41 @@ import { ROUTES } from '@/constants' import { Metadata } from 'next' import { ScoreList } from '../score-list' import { useEffect, useState } from 'react' +import { API } from '@/services/server' export const metadata: Metadata = { title: 'SPEED PUZZLE - 2023', description: 'Version - 2', } -export const Home = ({ scores, cookie }: { scores: any[]; cookie: any }) => { +export const Home = ({ cookie }: { cookie: any }) => { const router = useRouter() const [userName, setUserNamme] = useState() + const [scores, setScores] = useState([]) + + // const getHigherScores = async () => { + // const response = await API.getHighestScores() + // if (response) { + // console.log('getHigherScores response status', response.status) + // const result = await response.json() + // // const { scores } = result + // // const scoresParsed = Scores.getScoresParsedAndOrdered(scores) + // // console.log('getHigherScores scoreParsed', scoresParsed) + // console.log('test onClick result', result) + // } + // } useEffect(() => { - router.refresh() - }, [router]) + const getHigherScores = async () => { + const response = await API.getHighestScores() + if (response) { + console.log('getHigherScores response status', response.status) + const result = await response.json() + setScores(result?.scores) + } + } + getHigherScores() + }, []) useEffect(() => { if (cookie) {