Hosting·4 min lezen

Next.js 16 op een oudere iPhone: de pagina doet niets

Next.js 16 ondersteunt Safari vanaf 16.4. Op een iPhone met iOS 15 stopt het script met een syntaxfout en wordt de pagina nooit interactief. Zo meet je of het jou raakt, en zo repareer je het.

Kijk in de statistieken van deze website naar de afgelopen drie maanden.
Welke besturingssystemen en browserversies gebruiken mijn bezoekers, en
hoeveel sessies kwamen er van iOS 15 of ouder?

Je zet een nieuwe Next.js-site live, alles werkt, en dan belt iemand met een oudere iPhone. De pagina laadt wel, maar er gebeurt niets. Menu's klappen niet uit, formulieren versturen niet, knoppen doen niet mee. Op elke andere telefoon in het kantoor werkt het prima.

Dat is bijna altijd hetzelfde probleem, en het is geen fout in je eigen code.

Wat er gebeurt

Next.js 16 gaat ervan uit dat je bezoeker Safari 16.4 of nieuwer heeft. Dat is Safari uit het voorjaar van 2023. In de code die Next zelf meestuurt, zit een stuk moderne JavaScript dat oudere Safari-versies niet kennen: een zogeheten class static block.

Een browser leest een scriptbestand eerst helemaal in voordat hij er iets mee doet. Komt hij daarbij iets tegen dat hij niet kan lezen, dan stopt hij met dat hele bestand. Op iOS 15 zie je in de console van die telefoon dit:

SyntaxError: Unexpected token '{'

Daarmee valt het stuk code uit dat de pagina in de browser moet overnemen. De HTML van de server staat er nog wel, dus je ziet tekst en plaatjes, maar React neemt de pagina nooit over. Die overname heet hydratie, en zonder hydratie is je pagina een plaatje van een website.

Let op het verschil met de React-fouten 418, 423 en 425. Die gaan over hydratie die wél gebeurt en zichzelf herstelt. Dit is een stap eerder: het script wordt niet eens uitgevoerd.

Eerst meten, dan repareren

Voordat je iets verandert: kijk hoeveel bezoekers dit raakt. Je vindt dat in je eigen statistieken, uitgesplitst per besturingssysteem en versie. Bij een site die wij bewaken waren dat 0 van de 515 sessies over 90 dagen op iOS 15 of ouder.

Nul is een prettig getal, want dan is de goede beslissing: niets doen, en dit opschrijven zodat je het weet als er over een jaar iemand belt. Zie je wel een paar procent, bijvoorbeeld bij een publiek dat ouder is of bij een site die veel wordt gedeeld via oudere toestellen, dan is het de moeite waard.

Wat je niet moet doen is dit op gevoel beslissen. "Niemand gebruikt nog iOS 15" is een aanname, en als je het mis hebt, is het een stille storing: die bezoekers melden niets, ze gaan weg.

De reparatie

In package.json zet je een browserslist met de oudste browsers die je wilt bedienen:

"browserslist": [
  "chrome 111",
  "edge 111",
  "firefox 111",
  "safari 15"
]

Dat werkt omdat Turbopack die lijst ook toepast op de code van Next zelf, niet alleen op jouw eigen bestanden. Het class static block wordt dan herschreven naar iets dat Safari 15 wel leest. Wij hebben dat getest en de syntaxfout verdwijnt ermee.

Twee dingen om erbij te weten. Je stapt hiermee buiten wat Next.js officieel ondersteunt, dus test je site echt op zo'n toestel of simulator voordat je het live zet. En je levert iedereen iets oudere, iets grotere JavaScript. Dat verschil is klein, maar het is er, en daarom is die meting uit de vorige paragraaf geen formaliteit.

Hoe je het terugvindt in de praktijk

Dit probleem komt zelden netjes in een foutlog terecht. Het is geen React-melding met een nummer en het is geen serverfout: het gebeurt in de browser van één bezoeker voordat jouw eigen foutmelder is geladen. In de praktijk vind je het op drie manieren.

  • Een melding van een bezoeker die zegt dat de site "niet reageert" en niet dat er een foutmelding staat.
  • De console van het toestel zelf, als je er een kunt lenen of een simulator kunt openen.
  • Je statistieken, waarin een hele groep toestellen een opvallend hoog percentage bezoeken van één pagina heeft en vrijwel geen vervolgstappen.

Die derde is de nuttigste, want die werkt zonder dat je het toestel in handen hebt.

Veelgemaakte fouten

"Ik zet de cache leeg, dan is het vast weg." Dit zit niet in de cache. Hetzelfde bestand faalt op dat toestel elke keer opnieuw, en werkt op alle andere toestellen gewoon.

"Ik zie een wit scherm, dus de server is stuk." Kijk eerst of de HTML er is. Komt er wel tekst, maar werkt er niets, dan zit het probleem in de browser en niet op de server. Komt er niets, dan is het iets anders.

"Ik voeg een browserslist toe en ben klaar." Niet zonder test. Kijk na de aanpassing of de site het op het oude toestel echt doet, en of hij op een nieuwe telefoon niet iets anders is geworden.

"Ik los het op met een melding dat de bezoeker moet updaten." Dat kan, maar bedenk dat het script dat die melding zou tonen vaak in hetzelfde bestand zit dat niet laadt. Een waarschuwing die je in de HTML van de server zet, komt wel aan.

"Dit geldt alleen voor Next.js." Het patroon geldt voor elk gebouwd frontend-project: de ondergrens van je bouwgereedschap bepaalt stilletjes wie je site kan gebruiken. Zoek die ondergrens op voordat je upgradet, niet nadat iemand belt. Voor de rest van wat er bij deze versie veranderde: Next.js 16, wat stilletjes breekt.

MK
Maarten Keizer

Oprichter van Invoker. Ruim twintig jaar hosting, systeembeheer en webdevelopment; bouwt de Claude-hosting zelf en test alles eerst op de eigen servers.

over maarten