refactor(detail): render sections on the server behind a client shell
page.tsx now composes the sections and passes them through SchoolDetailShell
as children, so ~1,300 lines of static markup stop shipping as client
JavaScript. The shell keeps what is genuinely interactive: back link, header
reveal, hero map, compare CTA, sticky nav and scroll-spy.
The scroll-spy already located sections via document.getElementById, so it
works unchanged against server-rendered children.
Charts needed a client wrapper: next/dynamic with ssr:false is illegal in a
Server Component, so components/school/charts.tsx is the boundary that keeps
Chart.js (64 KB gz) lazy and browser-only.
Measured on this build:
- school route client chunk: 8 KB gz (33 KB raw)
- total static JS across all chunks: 380.6 -> 350.7 KB gz
- section markup is absent from every client chunk ("Got their first choice",
"Ofsted reports", "Most deprived" etc. all return 0 hits); shell strings
still present, as expected
- shared baseline unchanged at 172 KB gz -- out of scope, as designed
The 14 characterization tests pass byte-identical to the commit that
introduced them. Only the render helper changed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
'use client';
|
||||
|
||||
/**
|
||||
* Client wrappers for the lazily-loaded charts.
|
||||
*
|
||||
* `next/dynamic` with `ssr: false` is only legal inside a Client Component,
|
||||
* and the sections that render charts are Server Components. These one-line
|
||||
* wrappers are the client boundary, so the charts stay browser-only and
|
||||
* code-split while the section markup around them stays on the server.
|
||||
*
|
||||
* Chart.js is ~64 KB gzipped, so keeping it lazy matters.
|
||||
*/
|
||||
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
export const PerformanceChart = dynamic(
|
||||
() => import('../PerformanceChart').then((m) => m.PerformanceChart),
|
||||
{ ssr: false },
|
||||
);
|
||||
|
||||
export const SatsChart = dynamic(() => import('../SatsChart'), { ssr: false });
|
||||
|
||||
export const AdmissionsTrendChart = dynamic(
|
||||
() => import('../AdmissionsTrendChart'),
|
||||
{ ssr: false },
|
||||
);
|
||||
Reference in New Issue
Block a user