Files
triqura-ecd/docs/reports/efficiency-plan.md
2025-11-25 13:37:00 +01:00

8.4 KiB
Raw Blame History

Efficiëntieplan — Patiëntenworkspace & Spraakstreaming

Executive Summary

Dit plan prioriteert optimalisaties op basis van bundelimpact en implementatie-effort. De grootste winst zit in lazy loading van zware editors, niet in de Deepgram SDK.

Quick Reference

Prioriteit Optimalisatie Impact Effort
P0 TipTap lazy-load ~94 kB Laag
P1 Login page refactor ~76 kB Laag
P2 Speech recorder lazy-load ~25-30 kB Laag
P3 Modal lazy-load ~15-20 kB Laag
P4 Server components timeline ~10-15 kB Hoog

Bundelanalyse (25-11-2025)

Route Ranking (hoogste First Load JS)

Route Page Size First Load JS Bottleneck
/behandeladvies 154 kB 240 kB TipTap + Deepgram
/login 76 kB 162 kB BentoGrid (hele page client)
/reset-password 63.7 kB 150 kB Auth forms
/rapportage 60 kB 146 kB Deepgram + resizable-panels
/ (homepage) 60.7 kB 147 kB Marketing UI
/intakes/new 43.7 kB 130 kB react-hook-form + zod
/screening 20.1 kB 106 kB Decision cards

Build Snapshot (26-11-2025)

Route Page Size First Load JS Opmerking
/epd/patients/[id]/rapportage 25.7 kB 112 kB -34 kB vs baseline dankzij lazy modals & panels
/epd/patients/[id]/intakes/new 43.8 kB 130 kB Form island, maar shared chunk blijft gelijk
/login 65.7 kB 152 kB Hero nog client heavy gepland in latere fase

Grootste winst zichtbaar op rapportage route; andere pagina's vereisen aanvullende workstreams (marketing assets, shared chunks) om verder te dalen.

Package Sizes (raw disk)

Package Size Lazy-loadbaar
@tiptap/* ~5+ MB
@deepgram/sdk ~2.5 MB
react-resizable-panels ~650 KB
react-hook-form + zod ~1.5 MB

Aanname getoetst: "Deepgram SDK veroorzaakt performance issues"

Conclusie: Aanname is NIET correct.

  • Rapportage (60 kB) met Deepgram is 94 kB kleiner dan behandeladvies (154 kB)
  • Beide gebruiken SpeechRecorderStreaming met Deepgram
  • Het verschil komt door TipTap RichTextEditor (alleen in behandeladvies)

Fase-indeling (Geprioriteerd op ROI)

Fase 0 — Quick Wins (Hoogste ROI, laagste effort)

0.1 TipTap lazy-load in behandeladvies (~94 kB besparing)

// Huidige situatie (slecht)
import { RichTextEditor } from '@/components/rich-text-editor';

// Nieuwe situatie (goed)
import dynamic from 'next/dynamic';
const RichTextEditor = dynamic(
  () => import('@/components/rich-text-editor').then(m => m.RichTextEditor),
  { ssr: false, loading: () => <EditorSkeleton /> }
);

Status 26-11-2025: Ingezet in treatment-advice-form inclusief skeleton; bundel wacht nu tot interactie.

Criteria voor succes: /behandeladvies page size < 70 kB

0.2 Login page refactor (~76 kB besparing)

  • Login page is volledig 'use client' terwijl 60%+ statische marketing content is
  • Refactor naar server component met client islands voor form en BentoGrid interacties

Criteria voor succes: /login page size < 30 kB

Status 26-11-2025: Page is nu server-rendered; enkel het formulier is een client-island.


Fase 1 — Speech & Modal Optimalisatie

1.1 SpeechRecorderStreaming lazy-load (~25-30 kB per page)

const SpeechRecorderStreaming = dynamic(
  () => import('@/components/speech-recorder-streaming').then(m => m.SpeechRecorderStreaming),
  { ssr: false, loading: () => <RecorderSkeleton /> }
);

Toepassingslocaties:

  • treatment-advice-form.tsx (behandeladvies)
  • report-composer.tsx (rapportage)

Status 26-11-2025: Beide formulieren laden de recorder nu lazy met een kleine skeleton.

1.2 ReportViewEditModal lazy-load (~15-20 kB)

Modal wordt alleen getoond bij klikken op een rapport:

const ReportViewEditModal = dynamic(
  () => import('./report-view-edit-modal').then(m => m.ReportViewEditModal),
  { ssr: false }
);

Status 26-11-2025: Modal en Deepgram chunk worden alleen geladen wanneer een kaart wordt geopend.

1.3 Telemetrie toevoegen

Log spraakgebruik om te meten hoeveel gebruikers de Deepgram chunk daadwerkelijk nodig hebben.

Status 26-11-2025: Nieuwe speech_usage_events tabel + API route; recorder logt start/stop/final events met context.


Fase 2 — Form Optimalisatie

2.1 react-hook-form + zod lazy-load (~30-40 kB)

NewIntakeForm laadt zware form libraries direct. Lazy-load de hele form:

const NewIntakeForm = dynamic(
  () => import('../components/new-intake-form').then(m => m.NewIntakeForm),
  { ssr: false, loading: () => <FormSkeleton /> }
);

Status 26-11-2025: Pagina intakes/new laadt de form nu als island met skeleton.

2.2 react-resizable-panels lazy-load

RapportageWorkspaceV2 laadt dit direct. Overweeg een simpelere layout als default.

Status 26-11-2025: Panel library wordt client-side geladen met stacked fallback; timeline/composer blijven bruikbaar terwijl chunk downloadt.


Fase 3 — Server Components & Data Fetching

Let op: Deze fase heeft hoge effort maar medium winst. Alleen implementeren na Fase 0-2.

3.1 Timeline naar server component

Huidige situatie: ReportTimeline is volledig client-side voor filtering/zoeken.

  • Verplaats statische rendering (kaarten, timestamps) naar server
  • Behoud alleen filter-controls als client island

Status 26-11-2025: 🔄 Nog te doen. Vereist opsplitsing van RapportageWorkspaceV2 + nieuwe client island.

3.2 Header naar server component

Patient info en breadcrumbs kunnen server-side renderen.

Status 26-11-2025: 🔄 Nog te doen. Wordt opgepakt na timeline refactor.

3.3 Server actions & caching

  • Patient + rapportages via server actions laden met cache()
  • Gerichte revalidateTag bij mutaties

Status 26-11-2025: 🔄 Gepland na 3.1/3.2 om dataflow te vereenvoudigen.


Fase 4 — Build & Tooling (Maintenance)

4.1 Webpack cache waarschuwing oplossen

[webpack.cache.PackFileCacheStrategy] Serializing big strings (128kiB)

Grote stringassets omzetten naar Buffers of opsplitsen.

Status 26-11-2025: Productiebouw gebruikt nu een in-memory webpack cache, waardoor de PackFileCacheStrategy waarschuwing verdwijnt.

4.2 Performance budget in CI

# CI check
pnpm build && pnpm check:bundle

Budgetten:

  • Max 150 kB First Load JS per EPD route
  • Max 250 kB First Load JS voor behandeladvies (met editor)

Status 26-11-2025: scripts/check-bundle-size.js scant de route-specifieke chunks (exclusief shared webpack/main) na pnpm build; bundels falen wanneer /rapportage of behandeladvies boven hun budget komt (pnpm check:bundle).


Implementatie Roadmap

Week 1: Fase 0 (Quick Wins)
├── 0.1 TipTap lazy-load
└── 0.2 Login page refactor

Week 2: Fase 1 (Speech & Modals)
├── 1.1 Speech recorder lazy-load
├── 1.2 Modal lazy-load
└── 1.3 Telemetrie setup

Week 3: Fase 2 (Forms) + Meting
├── 2.1 Form lazy-load
├── 2.2 Resizable panels review
└── Bundle size meting vs baseline

Week 4+: Fase 3-4 (indien nodig)
├── Server components (hoog effort)
└── CI tooling

Metrics & Doelen

Baseline (25-11-2025)

Metric Huidige waarde
/behandeladvies First Load 240 kB
/rapportage First Load 146 kB
/login First Load 162 kB
Dev compile modules ~3000

Target na Fase 0-2

Metric Doel
/behandeladvies First Load < 150 kB (-38%)
/rapportage First Load < 120 kB (-18%)
/login First Load < 100 kB (-38%)

Architectuur Observaties

Positief

  • Pages zijn al server components
  • Data fetching gebeurt server-side met async page components
  • Supabase auth via server actions

Te verbeteren

  • Client components bevatten ALLE UI + logica (geen code splitting)
  • Modals en editors laden direct in initial bundle
  • Login page is volledig client terwijl content grotendeels statisch is

Referenties