Unsere Next.js-Seiten wurden Bing zu gross. Der RSC-Payload war 58 % des HTML
Drei Next.js-Seiten hingen bei entdeckt, aber nicht gecrawlt in Bing. Der App Router schickt jedes Byte zweimal. Wir haben eine um 48 KB gekuerzt, Bing hat sie indexiert.
8. Oktober 2026
Katto ist ein KI-Tool zum Zuschneiden von Videos. Man gibt ihm ein langes Video, es findet die besten Momente und schneidet sie zu vertikalen Clips mit Untertiteln. Ich baue es allein, öffentlich, mit Next.js und dem App Router. Das hier ist eine Messung, die meine Art, Seiten zu schreiben, verändert hat, eine Zahl, die ich vor allen als sicher ausgegeben habe und die falsch war, und eine eigene Hypothese, die 108 Bytes wert war.
Das Symptom
Die Bing Webmaster Tools führten mehrere unserer Seiten als entdeckt, aber nie gecrawlt. Nicht durch robots.txt blockiert, kein noindex, nicht langsam, keine Weiterleitung. Entdeckt und dann fallen gelassen. Google hatte sie im Index. Unsere Sitemap listete sie. Sie antworteten jedem mit 200.
Die abgelehnten Seiten hatten eines gemeinsam, und es war nicht ihr Inhalt.
Die Grenze, und wie ungenau wir sie kennen
Microsoft veröffentlicht keine Größe, ab der sein Crawler aufgibt. Was wir haben, sind unsere eigenen Seiten, jede mit dem in den Bing Webmaster Tools abgelesenen Status und der am selben Tag gemessenen ausgelieferten Größe, unkomprimiert, mit dem User Agent von bingbot:
/contact, 46.111 Bytes: indexiert./changelog, 103.058 Bytes: indexiert./roadmap, 116.239 Bytes: indexiert./compare/opusclip, 127.182 Bytes: indexiert./compare/ai-video-clippers, 127.951 Bytes: indexiert./compare/, 140.686 Bytes: entdeckt, aber nicht gecrawlt.
Eine einzige Seite jenseits einer Linie ist kein Gesetz. Aber in dieser Liste steckt eine Beobachtung, die mehr wert ist als alles andere, weil es zweimal dieselbe URL ist. /compare/ai-video-clippers lieferte 172.295 Bytes aus und hing wochenlang auf entdeckt, aber nicht gecrawlt fest. Wir haben sie auf rund 124 KB gekürzt. Heute ist sie indexiert, mit 127.951 Bytes. Dieselbe URL, dasselbe Template, dieselbe Art Inhalt: zu groß, dann klein genug.
Vor einer Woche hätte ich eine andere Zahl genannt, und sie wäre falsch gewesen. Ich hatte drei Statusmeldungen und eine auffällige Lücke in der Verteilung unserer Seitengrößen, und ich habe eine Grenze bei etwa 125 KB hineingelesen. Zwei dieser Seiten sind seitdem mit knapp unter 128 KB indexiert worden. Was unsere eigene Website wirklich sagen kann, ist, dass die Linie zwischen 128 und 140 KB liegt, und dass ihre andere Seite noch immer genau eine Seite breit ist.
Wenn Sie wegen einer Zahl hier sind: die ehrliche Antwort ist, Ihre eigene zu messen. Die Behauptung, die ich verteidigen kann, ist ohnehin enger und nützlicher. Eine Seite, die bei entdeckt hängen bleibt, lohnt sich zu wiegen, bevor sie sich lohnt umzuschreiben, und eine Seite, die nach dem Abspecken gecrawlt wird, ist der einzige Beweis, der wirklich zählt.
Die Quelldatei zu wiegen sagt nichts
Hier kommt der Teil, der spezifisch für React Server Components ist. Der App Router serialisiert den gerenderten Baum in dasselbe HTML-Dokument, als Folge von self.__next_f.push(...)-Skript-Tags, damit eine clientseitige Navigation ohne weiteren Roundtrip fortsetzen kann. Diese Payload ist keine separate Anfrage, die ein Crawler überspringen kann. Sie steht im Dokument.
Auf einer unserer Seiten gemessen: 125.981 ausgelieferte Bytes, davon 73.571 für diese Payload. Achtundfünfzig Prozent des Dokuments sind die serialisierte Kopie dessen, was die übrigen zweiundvierzig Prozent bereits sagen.
Eine Utility-Klasse, die einmal in einer Schleife über 24 Zeilen geschrieben wird, geht also nicht 24-mal raus. Sie geht 48-mal raus.
Der Teil, für den ich am längsten gebraucht habe
Es verdoppelt nicht die Seite. Es verdoppelt jede Darstellung, die die Seite ohnehin schon trägt.
Unsere Roadmap rendert jeden Eintrag absichtlich zweimal: einmal als sichtbaren Text, einmal in einem ItemList-Block aus JSON-LD, damit maschinelle Leser Name, Datum und Status als Daten bekommen statt als zu deutende Prosa. Vernünftig. Dann habe ich gezählt, wie oft die Beschreibung eines einzigen Eintrags im ausgelieferten Dokument vorkommt, und kam auf vier.
Zwei Darstellungen, jede verdoppelt. Vier Kopien desselben Satzes, und ich war nie auf die Idee gekommen zu zählen.
Die Lösung war keine Kompression. Das JSON-LD trug eine description, die wortwörtlich einen Text kopierte, den der Leser dreißig Zeilen tiefer sieht, in derselben Sprache. Sie brachte nichts und kostete zwei der vier Kopien. Entfernt behält der Block Name, Datum und Status, also genau das, was die Prosa einer Maschine nicht ausdrücklich sagt. Diese Seite ging von 121.196 auf 115.350 Bytes zurück, ohne dass Information verloren ging. Beide Zahlen stammen aus demselben Build, vor und nach dieser einen Änderung, und nur so bedeutet ein Vorher und Nachher überhaupt etwas.
Wenn Sie eine Gewohnheit mitnehmen: Bevor Sie irgendetwas verkleinern, zählen Sie, wie oft ein Satz Ihres Inhalts im ausgelieferten Dokument vorkommt. Das beantwortet eine Frage, die das Wiegen von Abschnitten nicht beantwortet.
Die zwei größeren Hebel
Wiederholte Klassenattribute in Stylesheet-Regeln. Tailwind-Utilities sind herrlich billig zu schreiben, und sie gehen an jedem Element mit, zweimal. Die wiederholten in @apply-Regeln zu verschieben, brachte unseren Preisindex von 172.295 Bytes auf rund 142.000. Sie machten etwa 51 Prozent des Markups aus.
Nicht interaktive Blöcke aus dem serialisierten Baum heraus. Um genau zu sein, weil es darauf ankommt: Das sind Server Components, sie werden auf dem Client also nie hydriert. Die Kosten sind nicht die Hydration, sondern die Serialisierung. Jedes Element, jede Prop und jeder Key wird in den Flight-Payload geschrieben, damit eine clientseitige Navigation den Baum ohne Roundtrip wieder aufbauen kann. Eine statische Tabelle ohne jedes Client-Verhalten zahlt das trotzdem, und wenn die Dokumentgröße die Schranke ist, gibt es keinen Grund, dass sie überhaupt React-Elemente bleibt. Wir bauen solche Blöcke jetzt aus denselben Daten als HTML-String und setzen sie mit dangerouslySetInnerHTML, wobei jeder interpolierte Wert beim Bauen escaped wird, damit das Escaping nicht davon abhängt, woher die Daten kamen. Weitere 18 KB beim Preisindex. Eine Liste mit 54 Zeilen auf der Roadmap ging auf demselben Weg von 157.308 auf 119.031.
Was nicht funktioniert hat
Vor alldem war ich sicher, die Komponentengrenzen seien das Problem. Vierundfünfzig next/link-Komponenten in einer Liste, jede mit ihrem serialisierten Namen, ihren Props und Keys in der Payload. Ich habe alle 54 durch einfache Anker ersetzt.
Das sparte 108 Bytes von 157.200.
Link ist billig. Der Inhalt, den er umschließt, nicht. Ich hätte einen Tag damit verbracht, Komponenten nach dieser Theorie umzuschreiben, hätte ich nicht vorher und nachher gemessen, und dieses negative Ergebnis war die nützlichste Zahl des Tages.
Es gibt einen Boden, und er ist nicht niedrig
Unsere leichteste echte Seite, /contact, liefert 46.111 Bytes aus und trägt dabei nur eine Überschrift, ein kurzes Formular und ein paar Fragen. Der Rest ist Navigation, Footer, Analytics und Schriften. Unterhalb dieser Zahl ist Seite für Seite nichts mehr zu holen; das wäre ein Rumpf-Projekt, kein Seiten-Projekt. Den Boden zu kennen sagt einem, wann man aufhören soll.
Eine Übersetzung kostet Bytes, nicht Wörter
Wir haben diese Roadmap in zehn Sprachen gebracht. Gleiches Markup, gleiche Struktur, gleiche Information. Die englische Seite liefert 116.239 Bytes aus, die französische 119.838, die japanische 122.155 und die Hindi-Seite 135.379.
Devanagari braucht in UTF-8 drei Bytes pro Zeichen, wo lateinischer Text eines braucht, und die Payload zahlt es ein zweites Mal. Keine Technik auf Seitenebene rührt daran: gleiches Markup, gleiche Information, neunzehn Kilobytes auseinander.
Die Hindi-Seite ist die interessante, denn mit 135.379 Bytes fällt sie mitten in das Band, das wir nicht auflösen können. Ob Bing sie verarbeitet, ist das billigste Experiment, das uns zur Verfügung steht, und es kostet eine URL-Prüfung.
Ich hatte hier einen Absatz geschrieben, der argumentierte, der Überhang sei nicht so wichtig, weil er ans Ende des Dokuments fällt und das Ende dieser Seite eine Liste ist, deren Titel ohnehin englisch bleiben. Ich habe ihn gestrichen, weil er unterstellt, der Crawler lese, bis sein Budget aufgebraucht ist, und höre dann auf. Alles, was ich tatsächlich beobachtet habe, sagt nur, dass Seiten über einer bestimmten Größe nicht verarbeitet werden. Wird das Dokument als Ganzes abgelehnt, kauft seine Reihenfolge nichts, und ich habe für keine der beiden Richtungen einen Beleg. Es ist eine bequeme Theorie über meine eigene Seite, und das ist die Sorte, die man am ehesten löschen sollte.
Es ist ein Budget, keine Reparatur
Der Preisindex, den ich von 172.295 auf 124.202 Bytes gebracht hatte, liegt heute bei 127.951, weil wir weiter etwas hinzugefügt haben: mehr Tools, mehr Spalten, zehn Übersetzungen. Er ist weiterhin indexiert, und genau darum geht es, und er ist zugleich wieder bis auf wenige Kilobytes an die Linie herangerückt. Es ist nichts schiefgegangen. Wir haben das Budget einfach erneut ausgegeben, ohne es im Blick zu behalten.
Das ist der eigentliche Schluss. In einem Framework, das seine eigene Ausgabe serialisiert, ist Seitengewicht keine Aufräumaktion, die man einmal macht. Es ist eine Zahl, die jedes Mal steigt, wenn jemand gute Arbeit leistet, und die einzige Verteidigung ist, das ausgelieferte Dokument statt der Quelle zu messen, eine Änderung nach der anderen.
So messen Sie Ihre eigenen
- Rufen Sie die URL ab und zählen Sie die Bytes des Antwortkörpers, unkomprimiert. Das ist, was der Crawler bekommt, und nicht das, was Ihre Quelldatei nahelegt.
- Zählen Sie, wie oft ein unverwechselbarer Satz Ihres Inhalts in diesem Körper vorkommt. Mehr als einmal heißt, Sie zahlen ihn mehr als einmal, und es zeigt auf das Duplikat.
- Messen Sie nach jeder einzelnen Änderung neu, getrennt. Zwei Änderungen auf einmal verdecken diejenige, die nichts gebracht hat.
- Lesen Sie danach den Status in den Bing Webmaster Tools erneut ab, für dieselbe URL. Eine aus fremden Seiten abgeleitete Grenze ist eine Vermutung. Eine eigene Seite, die nach dem Abspecken gecrawlt wird, ist eine Messung.
Ähnliche Artikel
Bereit, deine Videos in virale Clips zu verwandeln?
Katto schneidet, untertitelt und rahmt deine langen Videos automatisch zu Kurzform-Content um.
Katto kostenlos testen →