perf: edge-cache static assets and shrink org-route bundle
The /org/[slug] routes loaded 250+ JS chunks and, after a deploy, every chunk missed Cloudflare's edge cache and stampeded the single origin (up to 48s to serve one static file) — the "keeps loading" lockout. - tenant-router: opt /_app/immutable/* into the edge cache via cf.cacheEverything; setting Cache-Control alone never populated it - course/api: mark the 14 API singletons /* @__PURE__ */ so the barrel tree-shakes instead of dragging every API into each importer - courses page: import directly instead of via the feature barrels Cuts the courses route from 257 to 225 static chunks and keeps static assets off the origin after the first edge fill.
This commit is contained in:
@@ -63,4 +63,4 @@ export class AttendanceApi extends BaseApiWithErrors {
|
||||
}
|
||||
}
|
||||
|
||||
export const attendanceApi = new AttendanceApi();
|
||||
export const attendanceApi = /* @__PURE__ */ new AttendanceApi();
|
||||
|
||||
@@ -215,4 +215,4 @@ export class ComplianceApi extends BaseApiWithErrors {
|
||||
}
|
||||
}
|
||||
|
||||
export const complianceApi = new ComplianceApi();
|
||||
export const complianceApi = /* @__PURE__ */ new ComplianceApi();
|
||||
|
||||
@@ -59,4 +59,4 @@ export class ContentApi extends BaseApiWithErrors {
|
||||
}
|
||||
}
|
||||
|
||||
export const contentApi = new ContentApi();
|
||||
export const contentApi = /* @__PURE__ */ new ContentApi();
|
||||
|
||||
@@ -77,4 +77,4 @@ export class CourseCloneApi extends BaseApiWithErrors {
|
||||
}
|
||||
}
|
||||
|
||||
export const courseCloneApi = new CourseCloneApi();
|
||||
export const courseCloneApi = /* @__PURE__ */ new CourseCloneApi();
|
||||
|
||||
@@ -754,4 +754,4 @@ export class CourseApi extends BaseApiWithErrors {
|
||||
}
|
||||
}
|
||||
|
||||
export const courseApi = new CourseApi();
|
||||
export const courseApi = /* @__PURE__ */ new CourseApi();
|
||||
|
||||
@@ -171,4 +171,4 @@ export class CoursesApi extends BaseApiWithErrors {
|
||||
}
|
||||
}
|
||||
|
||||
export const coursesApi = new CoursesApi();
|
||||
export const coursesApi = /* @__PURE__ */ new CoursesApi();
|
||||
|
||||
@@ -70,4 +70,4 @@ class ExerciseTemplateApi extends BaseApi {
|
||||
}
|
||||
}
|
||||
|
||||
export const exerciseTemplateApi = new ExerciseTemplateApi();
|
||||
export const exerciseTemplateApi = /* @__PURE__ */ new ExerciseTemplateApi();
|
||||
|
||||
@@ -328,4 +328,4 @@ export class ExerciseApi extends BaseApiWithErrors {
|
||||
*/
|
||||
}
|
||||
|
||||
export const exerciseApi = new ExerciseApi();
|
||||
export const exerciseApi = /* @__PURE__ */ new ExerciseApi();
|
||||
|
||||
@@ -945,4 +945,4 @@ export class LessonApi extends BaseApiWithErrors {
|
||||
}
|
||||
}
|
||||
|
||||
export const lessonApi = new LessonApi();
|
||||
export const lessonApi = /* @__PURE__ */ new LessonApi();
|
||||
|
||||
@@ -35,4 +35,4 @@ export class MarkApi extends BaseApiWithErrors {
|
||||
}
|
||||
}
|
||||
|
||||
export const markApi = new MarkApi();
|
||||
export const markApi = /* @__PURE__ */ new MarkApi();
|
||||
|
||||
@@ -507,4 +507,4 @@ export class NewsfeedApi extends BaseApiWithErrors {
|
||||
}
|
||||
}
|
||||
|
||||
export const newsfeedApi = new NewsfeedApi();
|
||||
export const newsfeedApi = /* @__PURE__ */ new NewsfeedApi();
|
||||
|
||||
@@ -292,4 +292,4 @@ export class PeopleApi extends BaseApiWithErrors {
|
||||
}
|
||||
}
|
||||
|
||||
export const peopleApi = new PeopleApi();
|
||||
export const peopleApi = /* @__PURE__ */ new PeopleApi();
|
||||
|
||||
@@ -76,4 +76,4 @@ export class PresignApi extends BaseApiWithErrors {
|
||||
}
|
||||
}
|
||||
|
||||
export const presignApi = new PresignApi();
|
||||
export const presignApi = /* @__PURE__ */ new PresignApi();
|
||||
|
||||
@@ -159,4 +159,4 @@ export class SubmissionApi extends BaseApiWithErrors {
|
||||
}
|
||||
}
|
||||
|
||||
export const submissionApi = new SubmissionApi();
|
||||
export const submissionApi = /* @__PURE__ */ new SubmissionApi();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { CoursesPage } from '$features/course/pages';
|
||||
import { CreateCourseButton, CourseFilterPopover } from '$features/course/components';
|
||||
import CoursesPage from '$features/course/pages/courses.svelte';
|
||||
import CreateCourseButton from '$features/course/components/create-course-button.svelte';
|
||||
import CourseFilterPopover from '$features/course/components/course-filter-popover.svelte';
|
||||
import { courseMetaDeta } from '$features/course/utils/store';
|
||||
import {
|
||||
CourseSortBy,
|
||||
@@ -15,7 +16,7 @@
|
||||
import { t } from '$lib/utils/functions/translations';
|
||||
import { onMount } from 'svelte';
|
||||
import * as Page from '@cio/ui/base/page';
|
||||
import { coursesApi } from '$features/course/api';
|
||||
import { coursesApi } from '$features/course/api/courses.svelte';
|
||||
|
||||
let { data } = $props();
|
||||
const getInitialSelectedTags = () => data.activeTags ?? [];
|
||||
|
||||
@@ -265,17 +265,23 @@ export default {
|
||||
upstreamHeaders.set('x-forwarded-for', clientIp);
|
||||
}
|
||||
|
||||
// SvelteKit's immutable chunk filenames include a content hash, so they are
|
||||
// safe to cache at the edge forever. `cf.cacheEverything` is what actually
|
||||
// populates Cloudflare's edge cache for this subrequest — setting a
|
||||
// `Cache-Control` header on the response alone does NOT, so without this a
|
||||
// cold browser cache (new device, or post-deploy hash change) stampedes the
|
||||
// origin for every chunk.
|
||||
const isImmutableAsset = url.pathname.startsWith('/_app/immutable/');
|
||||
|
||||
const upstreamResponse = await fetch(upstreamUrl.toString(), {
|
||||
method: request.method,
|
||||
headers: upstreamHeaders,
|
||||
body: request.body,
|
||||
redirect: 'manual'
|
||||
redirect: 'manual',
|
||||
cf: isImmutableAsset ? { cacheEverything: true, cacheTtl: 31536000 } : undefined
|
||||
});
|
||||
|
||||
// SvelteKit's immutable chunk filenames include a content hash, so they
|
||||
// are safe to cache forever. Set a long TTL here at the edge so browsers
|
||||
// and Cloudflare cache them aggressively rather than revalidating.
|
||||
if (url.pathname.startsWith('/_app/immutable/')) {
|
||||
if (isImmutableAsset) {
|
||||
const response = new Response(upstreamResponse.body, upstreamResponse);
|
||||
response.headers.set('Cache-Control', 'public, max-age=31536000, immutable');
|
||||
return response;
|
||||
|
||||
Reference in New Issue
Block a user