Three.js Beheersen voor Marketing Sites
Er is een specifieke visuele taal die een uitzonderlijke marketingwebsite onderscheidt van een competente. Het is niet de copy, niet het kleurenpalet, zelfs niet de fotografie. Het is de aanwezigheid van iets dat werkelijk onmogelijk aanvoelt — een object dat licht buigt, reflecties opvangt en op je aanraking reageert op een manier die fysiek aanvoelt.
Dit is wat Three.js en WebGL mogelijk maken op het open web. En in 2025, dankzij het React Three Fiber-ecosysteem en bibliotheken als Drei, is de drempel enorm verlaagd. Maar het meesterschap — ervaringen bouwen die zowel visueel buitengewoon als technisch solide zijn — vereist nog steeds een diep begrip van hoe de GPU-pipeline werkt, hoe de browser resources laadt en hoe echte gebruikers met deze elementen omgaan op hun werkelijke apparaten.
Dit is die gids.
De Performance-uitdaging: Getallen die Tellen
Een naïeve Three.js-implementatie op een moderne marketingsite voegt toe:
- ~600KB JavaScript voor de Three.js-kern
- ~200KB voor
@react-three/drei(meer als je de hele bibliotheek importeert) - ~50KB voor
@react-three/fiber
Dat is ruwweg 850KB JavaScript voordat je rekening houdt met GLTF-modelbestanden, HDR-omgevingskaarten of aangepaste shader-code. Op een snelle glasvezelverbinding downloadt dit in minder dan een seconde. Op een 4G-verbinding in een landelijk gebied kan het 5-8 seconden duren. Dit zal je LCP-meting doen mislukken en je Google Search-ranking bestraffen.
Het doel is niet om Three.js te vermijden. Het doel is het intelligent te laden.
Strategie 1: Lazy Loading met next/dynamic
In Next.js stelt next/dynamic je in staat het laden van een component — en al zijn afhankelijkheden — uit te stellen totdat het component daadwerkelijk nodig is.
const HeroCanvas = dynamic(
() => import('./HeroCanvas'),
{ ssr: false }
);
De ssr: false-vlag voorkomt dat Next.js probeert het Three.js-canvas op de server te renderen (wat zou mislukken, omdat WebGL een browsercontext vereist). Het component wordt alleen gedownload en uitgevoerd wanneer het oudercomponent in de browser gemount wordt.
Voor maximale LCP-optimalisatie kun je verder gaan: wikkel het canvas in een IntersectionObserver en laad het Three.js-pakket pas wanneer het canvas-element voor het eerst het viewport binnenkomt.
Strategie 2: Verlaag het Polygoonantal Agressief
De meeste Three.js-demo's gebruiken polygoonaantallen die er indrukwekkend uitzien in screenshots maar volledig onnodig zijn voor een roterend achtergrondelement. De standaard TorusKnot-geometrie met argumenten [1.5, 0.5, 256, 64] genereert ongeveer 65.000 driehoeken. Dit terugbrengen naar [1.5, 0.5, 128, 32] resulteert in ~16.000 — een vermindering van 75% zonder zichtbaar verschil wanneer het mesh bedekt is door een transmissie-materiaal dat alle geometrische randen vervaagt.
Strategie 3: Beheers de Render-lus
Standaard rendert React Three Fiber de scène op elk browser-frame — tot 144 keer per seconde op hoge-verversingssnelheids-schermen. Voor een geanimeerde scène met een draaiend object en muisvolging is dit prima wanneer het element zichtbaar is. Maar wanneer de gebruiker voorbij de hero gescrold is, gaat het renderen door op de achtergrond, waarbij GPU-cycli onnodig worden verbruikt.
De prop frameloop="demand" op het Canvas-component schakelt over naar on-demand rendering. De scène rendert alleen opnieuw wanneer je expliciet state.invalidate() aanroept. Gecombineerd met een IntersectionObserver elimineert dit de GPU-belasting buiten het zichtbare scherm volledig.
<Canvas frameloop="demand" camera={{ position: [0, 0, 5] }}>
<AbstraktVorm isZichtbaar={heroIsInViewport} />
</Canvas>
Strategie 4: Beheer de DPR
Device Pixel Ratio (DPR) bepaalt hoeveel werkelijke pixels de GPU rendert per logische CSS-pixel. Op een iPhone 15 Pro is de DPR 3 — wat betekent dat een canvas van 390×844 CSS-pixels de GPU vereist om 1.170×2.532 fysieke pixels te renderen. Voor een complexe transmissieshader vermenigvuldigt dit het renderwerk met 9x vergeleken met een DPR van 1.
De dpr-prop op het Canvas-component laat je dit beperken:
<Canvas dpr={[1, 1.5]} frameloop="demand">
Dit vertelt React Three Fiber nooit meer dan 1,5x DPR te overschrijden, ongeacht de native DPR van het apparaat. Het visuele verschil is onwaarneembaar voor abstracte 3D-vormen. De prestatieverbetering op hoge-DPR mobiele apparaten is dramatisch.
Strategie 5: Optimaliseer MeshTransmissionMaterial
Voor refractie-materialen bepaalt de resolution-prop de grootte van de interne framebuffer die gebruikt wordt om te berekenen wat zichtbaar is door het glas. Een resolution={1024} maakt een 1024×1024 texture-map die elk frame bijgewerkt wordt. Verlagen naar resolution={256} behoudt het visuele effect terwijl geheugengebruik en GPU fill rate met 93% worden verminderd.
<MeshTransmissionMaterial
resolution={256}
backside={true}
thickness={2}
chromaticAberration={0.06}
temporalDistortion={0}
/>
Let op de instelling temporalDistortion={0}. Het temporele distorsie-effect creëert subtiel flikkeren door de refractiedata van het huidige en vorige frame te mengen. Het ziet er prachtig uit in beweging, maar vereist dat de scène continu rendert — waarmee de frameloop="demand"-optimalisatie teniet wordt gedaan.
Praktische Architectuur: Hoe We 3D-componenten Structureren
Onze aanpak scheidt verantwoordelijkheden in drie bestanden:
-
Scene.tsx— De daadwerkelijke Three.js-objecten, materialen enuseFrame-logica. Dit bestand importeert uitthreeen@react-three/drei. -
HeroCanvas.tsx— De<Canvas>-wrapper met camera, verlichting enEnvironment. Dit is het bestand dat lui geladen wordt vianext/dynamic. -
Hero.tsx— Het React-component dat zichtbaar is voor de rest van de applicatie. Het bevat deIntersectionObserver-logica, de tekstinhoud en eendynamic-import vanHeroCanvas. Dit bestand heeft geen Three.js-afhankelijkheden.
Deze architectuur zorgt ervoor dat de hero-tekst op de server rendert als statische HTML zonder enige JavaScript-afhankelijkheid op Three.js. Het 3D-canvas laadt op de achtergrond nadat de pagina interactief is. Lighthouse meet LCP aan de hand van de tekst — niet het canvas — en de score is consequent uitstekend.
Browser-ondersteuning en Fallbacks
WebGL 2 wordt nu ondersteund in 97% van de browsers wereldwijd, inclusief alle moderne mobiele browsers. Sommige oudere Android-apparaten en tablets met weinig vermogen ondersteunen echter mogelijk niet de specifieke extensies die transmissiematerialen vereisen.
Voeg altijd een graceful fallback toe. De eenvoudigste aanpak is om bij mount te controleren op WebGL-ondersteuning en een hoogwaardige CSS-gradiënt of statisch beeld te vervangen als het niet beschikbaar is. De ervaring degradeert elegant zonder te breken.
Conclusie
Three.js is een van de krachtigste tools voor het creëren van onvergetelijke web-ervaringen. Maar zoals elk krachtig gereedschap vereist het respect. Laad het lui. Verlaag geometrie. Beheers de render-lus. Stem de DPR af. Optimaliseer je materialen.
Wanneer al deze strategieën samenwerken, kun je een WebGL-hero leveren die 95+ scoort op Lighthouse, laadt in minder dan 1,5 seconden op 4G, en nog steeds de adem van je bezoeker wegneemt op het moment dat het op het scherm verschijnt.
Dat is de standaard die we onszelf opleggen. Het is haalbaar. Het vereist alleen discipline.