refactor: improve perf on the frontend

This commit is contained in:
swve 2025-03-16 15:23:02 +01:00
parent 5e7ae54215
commit 744e372f4e
8 changed files with 61 additions and 51 deletions

View file

@ -499,6 +499,7 @@ function ActivityChapterDropdown(props: {
<Link
key={activity.id}
href={getUriWithOrg(props.orgslug, '') + `/course/${cleanCourseUuid}/activity/${cleanActivityUuid}`}
prefetch={false}
onClick={() => setIsOpen(false)}
>
<div

View file

@ -11,25 +11,36 @@ type MetadataProps = {
searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}
type Session = {
tokens?: {
access_token?: string
}
}
// Add this function at the top level to avoid duplicate fetches
async function fetchCourseMetadata(courseuuid: string, access_token: string | null | undefined) {
return await getCourseMetadata(
courseuuid,
{ revalidate: 1800, tags: ['courses'] },
access_token || null
)
}
export async function generateMetadata(props: MetadataProps): Promise<Metadata> {
const params = await props.params;
const session = await getServerSession(nextAuthOptions)
const access_token = session?.tokens?.access_token
const session = await getServerSession(nextAuthOptions as any) as Session
const access_token = session?.tokens?.access_token || null
// Get Org context information
const org = await getOrganizationContextInfo(params.orgslug, {
revalidate: 1800,
tags: ['organizations'],
})
const course_meta = await getCourseMetadata(
params.courseuuid,
{ revalidate: 0, tags: ['courses'] },
access_token ? access_token : null
)
const course_meta = await fetchCourseMetadata(params.courseuuid, access_token)
const activity = await getActivityWithAuthHeader(
params.activityid,
{ revalidate: 0, tags: ['activities'] },
access_token ? access_token : null
{ revalidate: 1800, tags: ['activities'] },
access_token || null
)
// SEO
@ -57,32 +68,29 @@ export async function generateMetadata(props: MetadataProps): Promise<Metadata>
}
const ActivityPage = async (params: any) => {
const session = await getServerSession(nextAuthOptions)
const access_token = session?.tokens?.access_token
const session = await getServerSession(nextAuthOptions as any) as Session
const access_token = session?.tokens?.access_token || null
const activityid = (await params.params).activityid
const courseuuid = (await params.params).courseuuid
const orgslug = (await params.params).orgslug
const course_meta = await getCourseMetadata(
courseuuid,
{ revalidate: 0, tags: ['courses'] },
access_token ? access_token : null
)
const activity = await getActivityWithAuthHeader(
activityid,
{ revalidate: 0, tags: ['activities'] },
access_token ? access_token : null
)
const [course_meta, activity] = await Promise.all([
fetchCourseMetadata(courseuuid, access_token),
getActivityWithAuthHeader(
activityid,
{ revalidate: 1800, tags: ['activities'] },
access_token || null
)
])
return (
<>
<ActivityClient
activityid={activityid}
courseuuid={courseuuid}
orgslug={orgslug}
activity={activity}
course={course_meta}
/>
</>
<ActivityClient
activityid={activityid}
courseuuid={courseuuid}
orgslug={orgslug}
activity={activity}
course={course_meta}
/>
)
}

View file

@ -223,6 +223,7 @@ const CourseClient = (props: any) => {
)}`
}
rel="noopener noreferrer"
prefetch={false}
>
<p>{activity.name}</p>
</Link>
@ -240,6 +241,7 @@ const CourseClient = (props: any) => {
)}`
}
rel="noopener noreferrer"
prefetch={false}
>
<div className="text-xs bg-gray-100 text-gray-400 font-bold px-2 py-1 rounded-full flex space-x-1 items-center">
<p>Page</p>
@ -260,6 +262,7 @@ const CourseClient = (props: any) => {
)}`
}
rel="noopener noreferrer"
prefetch={false}
>
<div className="text-xs bg-gray-100 text-gray-400 font-bold px-2 py-1 rounded-full flex space-x-1 items-center">
<p>Video</p>
@ -281,6 +284,7 @@ const CourseClient = (props: any) => {
)}`
}
rel="noopener noreferrer"
prefetch={false}
>
<div className="text-xs bg-gray-100 text-gray-400 font-bold px-2 py-1 rounded-full flex space-x-1 items-center">
<p>Document</p>
@ -302,6 +306,7 @@ const CourseClient = (props: any) => {
)}`
}
rel="noopener noreferrer"
prefetch={false}
>
<div className="text-xs bg-gray-100 text-gray-400 font-bold px-2 py-1 rounded-full flex space-x-1 items-center">
<p>Assignment</p>

View file

@ -24,7 +24,7 @@ export async function generateMetadata(props: MetadataProps): Promise<Metadata>
})
const course_meta = await getCourseMetadata(
params.courseuuid,
{ revalidate: 0, tags: ['courses'] },
{ revalidate: 1800, tags: ['courses'] },
access_token ? access_token : null
)
@ -66,24 +66,23 @@ export async function generateMetadata(props: MetadataProps): Promise<Metadata>
}
const CoursePage = async (params: any) => {
const courseuuid = (await params.params).courseuuid
const orgslug = (await params.params).orgslug
const session = await getServerSession(nextAuthOptions)
const access_token = session?.tokens?.access_token
// Fetch course metadata once
const course_meta = await getCourseMetadata(
courseuuid,
{ revalidate: 0, tags: ['courses'] },
params.params.courseuuid,
{ revalidate: 1800, tags: ['courses'] },
access_token ? access_token : null
)
return (
<div>
<CourseClient
courseuuid={courseuuid}
orgslug={orgslug}
course={course_meta}
/>
</div>
<CourseClient
courseuuid={params.params.courseuuid}
orgslug={params.params.orgslug}
course={course_meta}
access_token={access_token}
/>
)
}

View file

@ -191,7 +191,6 @@ function ActivityElement(props: ActivitiyElementProps) {
''
)}`
}
prefetch
className="p-1 px-2 sm:px-3 bg-linear-to-bl text-cyan-800 from-sky-400/50 to-cyan-200/80 border border-cyan-600/10 shadow-md rounded-md font-bold text-xs flex items-center space-x-1 transition-colors duration-200 hover:from-sky-500/50 hover:to-cyan-300/80"
rel="noopener noreferrer"
>
@ -296,7 +295,6 @@ const ActivityElementOptions = ({ activity, isMobile }: { activity: any; isMobil
''
)}/edit`
}
prefetch
className={`hover:cursor-pointer p-1 ${isMobile ? 'px-2' : 'px-3'} bg-sky-700 rounded-md items-center`}
target='_blank'
>
@ -313,7 +311,6 @@ const ActivityElementOptions = ({ activity, isMobile }: { activity: any; isMobil
getUriWithOrg(org.slug, '') +
`/dash/assignments/${assignmentUUID}`
}
prefetch
className={`hover:cursor-pointer p-1 ${isMobile ? 'px-2' : 'px-3'} bg-teal-700 rounded-md items-center`}
>
<div className="text-sky-100 font-bold text-xs flex items-center space-x-1">

View file

@ -65,7 +65,7 @@ function ActivityIndicators(props: Props) {
key={activity.activity_uuid}
>
<Link
prefetch={true}
prefetch={false}
href={
getUriWithOrg(orgslug, '') +
`/course/${courseid}/activity/${activity.activity_uuid.replace(

View file

@ -111,11 +111,11 @@ export async function deleteActivity(activity_uuid: any, access_token: string) {
export async function getActivityWithAuthHeader(
activity_uuid: any,
next: any,
access_token: string
access_token: string | null | undefined
) {
const result = await fetch(
`${getAPIUrl()}activities/activity_${activity_uuid}`,
RequestBodyWithAuthHeader('GET', null, next, access_token)
RequestBodyWithAuthHeader('GET', null, next, access_token || undefined)
)
const res = await result.json()
return res

View file

@ -41,13 +41,13 @@ export async function searchOrgCourses(
}
export async function getCourseMetadata(
course_uuid: any,
course_uuid: string,
next: any,
access_token: string
access_token: string | null | undefined
) {
const result = await fetch(
`${getAPIUrl()}courses/course_${course_uuid}/meta`,
RequestBodyWithAuthHeader('GET', null, next, access_token)
RequestBodyWithAuthHeader('GET', null, next, access_token || undefined)
)
const res = await errorHandling(result)
return res