{"id":83276,"date":"2022-08-04T07:47:54","date_gmt":"2022-08-04T05:47:54","guid":{"rendered":"https:\/\/rmarketingdigital.com\/dev\/techniques-to-make-a-web-app-load-fast-even-on-a-feature-phone\/"},"modified":"2021-07-06T10:06:42","modified_gmt":"2021-07-06T08:06:42","slug":"techniques-to-make-a-web-app-load-fast-even-on-a-feature-phone","status":"publish","type":"post","link":"https:\/\/rmarketingdigital.com\/de\/dev\/techniques-to-make-a-web-app-load-fast-even-on-a-feature-phone\/","title":{"rendered":"Techniken, mit denen eine Web-App auch auf einem Feature-Telefon schnell geladen werden kann"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_86 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Inhalt<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Inhaltsverzeichnis umschalten\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Umschalten<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewbox=\"0 0 24 24\" version=\"1.2\" baseprofile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/rmarketingdigital.com\/de\/dev\/techniques-to-make-a-web-app-load-fast-even-on-a-feature-phone\/#Capturing-the-status-quo\" >Erfassen des Status Quo<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/rmarketingdigital.com\/de\/dev\/techniques-to-make-a-web-app-load-fast-even-on-a-feature-phone\/#Waterfall-analysis\" >Wasserfallanalyse<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/rmarketingdigital.com\/de\/dev\/techniques-to-make-a-web-app-load-fast-even-on-a-feature-phone\/#Reducing-connection-count\" >Verbindungsanzahl reduzieren<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/rmarketingdigital.com\/de\/dev\/techniques-to-make-a-web-app-load-fast-even-on-a-feature-phone\/#Parallelizing-loads\" >Lasten parallelisieren<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/rmarketingdigital.com\/de\/dev\/techniques-to-make-a-web-app-load-fast-even-on-a-feature-phone\/#Results\" >Ergebnisse<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/rmarketingdigital.com\/de\/dev\/techniques-to-make-a-web-app-load-fast-even-on-a-feature-phone\/#Prerendering\" >Vorrendern<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/rmarketingdigital.com\/de\/dev\/techniques-to-make-a-web-app-load-fast-even-on-a-feature-phone\/#Inlining\" >Inlining<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/rmarketingdigital.com\/de\/dev\/techniques-to-make-a-web-app-load-fast-even-on-a-feature-phone\/#Aggressive-code-splitting\" >Aggressive Code-Aufteilung<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/rmarketingdigital.com\/de\/dev\/techniques-to-make-a-web-app-load-fast-even-on-a-feature-phone\/#More-Sleight-of-Hand\" >Mehr Fingerspitzengef\u00fchl<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/rmarketingdigital.com\/de\/dev\/techniques-to-make-a-web-app-load-fast-even-on-a-feature-phone\/#Conclusion\" >Fazit<\/a><\/li><\/ul><\/nav><\/div>\n<p><\/p>\n<div>\n<header class=\"w-article-header\">\n<p class=\"w-article-header__subhead w-mb--non\">\n          Wie wir Code-Splitting, Code-Inlining und serverseitiges Rendern in PROXX verwendet haben.\n        <\/p>\n<p>\n          <time>23. September 2019<\/time><\/p>\n<\/header>\n<p>Bei Google I \/ O 2019 haben Mariko, Jake und ich versendet <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/proxx.app\">PROXX<\/a>, ein moderner Minesweeper-Klon f\u00fcr das Web. Was PROXX von anderen unterscheidet, ist der Fokus auf Barrierefreiheit (Sie k\u00f6nnen es mit einem Screenreader abspielen!) Und die F\u00e4higkeit, sowohl auf einem Feature-Telefon als auch auf einem High-End-Desktop-Ger\u00e4t ausgef\u00fchrt zu werden. Funktionstelefone sind in mehrfacher Hinsicht eingeschr\u00e4nkt:<\/p>\n<ul>\n<li>Schwache CPUs<\/li>\n<li>Schwache oder nicht vorhandene GPUs<\/li>\n<li>Kleine Bildschirme ohne Ber\u00fchrungseingabe<\/li>\n<li>Sehr begrenzte Speichermengen<\/li>\n<\/ul>\n<p>Aber sie betreiben einen modernen Browser und sind sehr erschwinglich. Aus diesem Grund erleben Feature-Telefone in Schwellenl\u00e4ndern eine Wiederbelebung. Ihr Preis erm\u00f6glicht es einem ganz neuen Publikum, das es sich bisher nicht leisten konnte, online zu gehen und das moderne Web zu nutzen. <strong><a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/www.counterpointresearch.com\/more-than-a-billion-feature-phones-to-be-sold-over-next-three-years\/\">F\u00fcr 2019 wird prognostiziert, dass allein in Indien rund 400 Millionen Feature-Telefone verkauft werden<\/a><\/strong>Daher werden Benutzer auf Funktionstelefonen m\u00f6glicherweise zu einem bedeutenden Teil Ihres Publikums. Dar\u00fcber hinaus sind Verbindungsgeschwindigkeiten \u00e4hnlich 2G in Schwellenl\u00e4ndern die Norm. Wie haben wir es geschafft, dass PROXX unter den Bedingungen eines Feature-Telefons gut funktioniert?<\/p>\n<figure class=\"w-figure\">\n  <video controls=\"\" loop=\"\" muted=\"\" preload=\"metadata\" class=\"w-screenshot\" poster=\"https:\/\/storage.googleapis.com\/web-dev-assets\/js-heavy-sites\/social_supercut_poster.jpg\" src=\"https:\/\/storage.googleapis.com\/web-dev-assets\/js-heavy-sites\/social_supercut_x264.mp4\" type=\"video\/mp4; codecs=h264\"><\/video><figcaption class=\"w-figcaption w-figcaption--fullbleed\">\n    PROXX Gameplay.<br \/>\n  <\/figcaption><\/figure>\n<p>Die Leistung ist wichtig und umfasst sowohl die Ladeleistung als auch die Laufzeitleistung. Es wurde gezeigt, dass <strong>Eine gute Leistung korreliert mit einer erh\u00f6hten Benutzerbindung, verbesserten Conversions und vor allem einer erh\u00f6hten Inklusivit\u00e4t.<\/strong> <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/twitter.com\/malchata\">Jeremy Wagner<\/a> hat viel mehr Daten und Einblicke in <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/developers.google.com\/web\/fundamentals\/performance\/why-performance-matters\/\">warum Leistung wichtig ist<\/a>.<\/p>\n<p>Dies ist Teil 1 einer zweiteiligen Serie. <strong>Teil 1 konzentriert sich auf die Ladeleistung<\/strong>Teil 2 konzentriert sich auf die Laufzeitleistung.<\/p>\n<h2 id=\"capturing-the-status-quo\"><span class=\"ez-toc-section\" id=\"Capturing-the-status-quo\"><\/span>Erfassen des Status Quo <span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Testen Sie Ihre Ladeleistung auf einem <em>echt<\/em> Ger\u00e4t ist kritisch. Wenn Sie kein echtes Ger\u00e4t zur Hand haben, empfehle ich <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/webpagetest.org\">WebPageTest<\/a> (WPT), speziell die <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/webpagetest.org\/easy\">&quot;Einfache&quot; Einrichtung<\/a>. <strong>WPT f\u00fchrt eine Reihe von Ladetests auf einem aus <em>echt<\/em> Ger\u00e4t mit emulierter 3G-Verbindung.<\/strong><\/p>\n<p>3G ist eine gute Messgeschwindigkeit. W\u00e4hrend Sie vielleicht an 4G, LTE oder bald sogar an 5G gew\u00f6hnt sind, sieht die Realit\u00e4t des mobilen Internets ganz anders aus. Vielleicht sind Sie in einem Zug, auf einer Konferenz, auf einem Konzert oder auf einem Flug. Was Sie dort erleben werden, ist h\u00f6chstwahrscheinlich n\u00e4her an 3G und manchmal sogar noch schlimmer.<\/p>\n<p>That being said, we&#8217;re going to focus on 2G in this article because PROXX is explicitly targeting feature phones and emerging markets in its target audience. Once WebPageTest has run its test, you get a waterfall (equivalente to what you see in DevTools) as well as a filmstrip at the top. The film strip shows what your user sees while your app is loading. On 2G, the loading experience of the unoptimized version of PROXX is pretty bad:<\/p>\n<figure class=\"w-figure\">\n  <video controls=\"\" muted=\"\" preload=\"metadata\" class=\"w-screenshot\" poster=\"https:\/\/storage.googleapis.com\/web-dev-assets\/js-heavy-sites\/stupid-proxx-load-poster.jpg\" src=\"https:\/\/storage.googleapis.com\/web-dev-assets\/js-heavy-sites\/stupid-proxx-load.mp4\" type=\"video\/mp4; codecs=h264\"><\/video><figcaption class=\"w-figcaption w-figcaption--fullbleed\">\n    Das Filmstreifenvideo zeigt, was der Benutzer sieht, wenn PROXX \u00fcber eine emulierte 2G-Verbindung auf ein echtes Low-End-Ger\u00e4t geladen wird.<br \/>\n  <\/figcaption><\/figure>\n<p>Beim Laden \u00fcber 3G sieht der Benutzer 4 Sekunden wei\u00dfes Nichts. <strong>\u00dcber 2G sieht der Benutzer \u00fcber 8 Sekunden absolut nichts.<\/strong> Wenn du liest <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/developers.google.com\/web\/fundamentals\/performance\/why-performance-matters\/\">warum Leistung wichtig ist<\/a> Sie wissen, dass wir jetzt einen gro\u00dfen Teil unserer potenziellen Benutzer aufgrund von Ungeduld verloren haben. Der Benutzer muss alle 62 KB JavaScript herunterladen, damit alles auf dem Bildschirm angezeigt wird. Der Silberstreifen in diesem Szenario ist, dass das zweite Element, das auf dem Bildschirm angezeigt wird, auch interaktiv ist. Oder ist es?<\/p>\n<figure class=\"w-figure\">\n  <picture><source srcset=\"https:\/\/web.dev\/proxx-first-render.webp\" type=\"image\/webp\"><img alt='proxx-first-render-4341069' src='https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/proxx-first-render-4341069.jpg'><br \/>\n  <\/source><\/picture><figcaption class=\"w-figcaption\">\n<p>Die erste sinnvolle Farbe in der nicht optimierten Version von PROXX ist <em>technisch<\/em> interaktiv, aber f\u00fcr den Benutzer nutzlos.<\/p>\n<\/figcaption><\/figure>\n<p>Nachdem ungef\u00e4hr 62 KB gzip&#039;d JS heruntergeladen und das DOM generiert wurden, kann der Benutzer unsere App sehen. Die App ist <em>technisch<\/em> interaktiv. Ein Blick auf das Visuelle zeigt jedoch eine andere Realit\u00e4t. Die Web-Schriftarten werden immer noch im Hintergrund geladen, und bis sie fertig sind, kann der Benutzer keinen Text sehen. W\u00e4hrend dieser Status als First Meaningful Paint (FMP) qualifiziert ist, gilt er sicherlich nicht als ordnungsgem\u00e4\u00df interaktiv, da der Benutzer nicht erkennen kann, worum es bei den Eingaben geht. Bei 3G dauert es eine weitere Sekunde und bei 2G 3 Sekunden, bis die App betriebsbereit ist. <strong>Insgesamt ben\u00f6tigt die App 6 Sekunden f\u00fcr 3G und 11 Sekunden f\u00fcr 2G, um interaktiv zu werden.<\/strong><\/p>\n<h2 id=\"waterfall-analysis\"><span class=\"ez-toc-section\" id=\"Waterfall-analysis\"><\/span>Wasserfallanalyse <span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Jetzt wo wir es wissen <em>que<\/em> Der Benutzer sieht, wir m\u00fcssen das herausfinden <em>Warum<\/em>. Dazu k\u00f6nnen wir uns den Wasserfall ansehen und analysieren, warum Ressourcen zu sp\u00e4t geladen werden. In unserem 2G-Trace f\u00fcr PROXX sehen wir zwei gro\u00dfe rote Fahnen:<\/p>\n<ol>\n<li>Es gibt mehrere mehrfarbige d\u00fcnne Linien.<\/li>\n<li>JavaScript-Dateien bilden eine Kette. Beispielsweise wird die zweite Ressource erst geladen, wenn die erste Ressource fertig ist, und die dritte Ressource startet erst, wenn die zweite Ressource fertig ist.<\/li>\n<\/ol>\n<figure class=\"w-figure\">\n  <picture>\n    <img alt='waterfall_opt-8683308' src='https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/waterfall_opt-8683308.png'>\n  <\/picture><figcaption class=\"w-figcaption\">\n    Der Wasserfall gibt Aufschluss dar\u00fcber, welche Ressourcen wann und wie lange geladen werden.<br \/>\n  <\/figcaption><\/figure>\n<h3 id=\"reducing-connection-count\"><span class=\"ez-toc-section\" id=\"Reducing-connection-count\"><\/span>Verbindungsanzahl reduzieren <span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Jede d\u00fcnne Linie (<code>DNS<\/code>, <code>verbinden<\/code>, <code>ssl<\/code>) steht f\u00fcr die Erstellung einer neuen HTTP-Verbindung. Das Einrichten einer neuen Verbindung ist kostspielig, da es bei 3G ungef\u00e4hr 1 Sekunde und bei 2G ungef\u00e4hr 2,5 Sekunden dauert. In unserem Wasserfall sehen wir eine neue Verbindung f\u00fcr:<\/p>\n<ul>\n<li>Anfrage #1: Unsere <code>index.html<\/code><\/li>\n<li>Anfrage #5: Die Schriftstile von <code>fonts.googleapis.com<\/code><\/li>\n<li>Anfrage #8: Google Analytics<\/li>\n<li>Anfrage #9: Eine Schriftartdatei von <code>fonts.gstatic.com<\/code><\/li>\n<li>Anforderung #14: Das Web-App-Manifest<\/li>\n<\/ul>\n<p>Die neue Verbindung f\u00fcr <code>index.html<\/code> ist unvermeidlich. Der Browser <em>hast du<\/em> um eine Verbindung zu unserem Server herzustellen, um den Inhalt zu erhalten. Die neue Verbindung f\u00fcr Google Analytics k\u00f6nnte vermieden werden, indem so etwas eingef\u00fcgt wird <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/minimalanalytics.com\">Minimale Analyse<\/a>Google Analytics verhindert jedoch nicht, dass unsere App gerendert wird oder interaktiv wird. Daher ist es uns egal, wie schnell sie geladen wird. Im Idealfall sollte Google Analytics im Leerlauf geladen werden, wenn alles andere bereits geladen wurde. Auf diese Weise wird beim ersten Laden weder Bandbreite noch Rechenleistung beansprucht. Die neue Verbindung f\u00fcr das Web-App-Manifest lautet <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/fetch.spec.whatwg.org\/#connections\">vorgeschrieben durch die Abrufspezifikation<\/a>, da das Manifest \u00fcber eine Verbindung ohne Berechtigungsnachweis geladen werden muss. Auch hier verhindert das Web-App-Manifest nicht, dass unsere App gerendert oder interaktiv wird, sodass wir uns nicht so sehr darum k\u00fcmmern m\u00fcssen.<\/p>\n<p>Die beiden Schriftarten und ihre Stile sind jedoch ein Problem, da sie das Rendern und auch die Interaktivit\u00e4t blockieren. Wenn wir uns das CSS ansehen, das von geliefert wird <code>fonts.googleapis.com<\/code>Es sind nur zwei <code>@ Schriftart<\/code> Regeln, eine f\u00fcr jede Schriftart. Die Schriftart <em>Stile<\/em> sind in der Tat so klein, dass wir beschlossen haben, sie in unseren HTML-Code einzuf\u00fcgen und eine unn\u00f6tige Verbindung zu entfernen. Um die Kosten f\u00fcr den Verbindungsaufbau f\u00fcr die Schriftart zu vermeiden <em>Dateien<\/em>k\u00f6nnen wir sie auf unseren eigenen Server kopieren.<\/p>\n<div class=\"w-aside w-aside--note\">\n<p><strong>Hinweis:<\/strong> Das Kopieren von CSS- oder Schriftdateien auf Ihren eigenen Server ist bei Verwendung in Ordnung <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/fonts.google.com\">Google Fonts<\/a>. Andere Schriftartenanbieter haben m\u00f6glicherweise andere Regeln. Bitte erkundigen Sie sich bei den Nutzungsbedingungen Ihres Schriftanbieters!<\/p>\n<\/div>\n<h3 id=\"parallelizing-loads\"><span class=\"ez-toc-section\" id=\"Parallelizing-loads\"><\/span>Lasten parallelisieren <span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Wenn wir uns den Wasserfall ansehen, k\u00f6nnen wir sehen, dass nach dem Laden der ersten JavaScript-Datei sofort neue Dateien geladen werden. Dies ist typisch f\u00fcr Modulabh\u00e4ngigkeiten. Unser Hauptmodul verf\u00fcgt wahrscheinlich \u00fcber statische Importe, sodass JavaScript erst ausgef\u00fchrt werden kann, wenn diese Importe geladen sind. Das Wichtigste dabei ist, dass diese Arten von Abh\u00e4ngigkeiten zum Zeitpunkt der Erstellung bekannt sind. Wir k\u00f6nnen davon Gebrauch machen <code>&lt;enlace rel=\"preload\"&gt;<\/code> Tags, um sicherzustellen, dass alle Abh\u00e4ngigkeiten in dem Moment geladen werden, in dem wir unseren HTML-Code erhalten.<\/p>\n<h3 id=\"results\"><span class=\"ez-toc-section\" id=\"Results\"><\/span>Ergebnisse <span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Werfen wir einen Blick darauf, was unsere \u00c4nderungen erreicht haben. Es ist wichtig, keine anderen Variablen in unserem Testaufbau zu \u00e4ndern, die die Ergebnisse verzerren k\u00f6nnten, daher werden wir sie verwenden <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/webpagetest.org\/easy\">Einfache Einrichtung von WebPageTest<\/a> f\u00fcr den Rest dieses Artikels und schauen Sie sich den Filmstreifen an:<\/p>\n<figure class=\"w-figure\">\n  <video controls=\"\" muted=\"\" preload=\"metadata\" class=\"w-screenshot\" poster=\"https:\/\/storage.googleapis.com\/web-dev-assets\/js-heavy-sites\/preload-proxx-load-poster.jpg\" src=\"https:\/\/storage.googleapis.com\/web-dev-assets\/js-heavy-sites\/preload-proxx-load.mp4\" type=\"video\/mp4; codecs=h264\"><\/video><figcaption class=\"w-figcaption w-figcaption--fullbleed\">\n    Wir verwenden den Filmstreifen von WebPageTest, um zu sehen, was unsere \u00c4nderungen erreicht haben.<br \/>\n  <\/figcaption><\/figure>\n<p><strong>Diese \u00c4nderungen reduzierten unseren TTI von 11 auf 8,5<\/strong>Dies entspricht ungef\u00e4hr den 2,5 Sekunden der Verbindungsaufbauzeit, die wir entfernen wollten. Gut gemacht uns.<\/p>\n<h2 id=\"prerendering\"><span class=\"ez-toc-section\" id=\"Prerendering\"><\/span>Vorrendern <span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>W\u00e4hrend wir gerade unseren TTI reduziert haben, haben wir den ewig langen wei\u00dfen Bildschirm, den der Benutzer 8,5 Sekunden lang aushalten muss, nicht wirklich beeinflusst. Wohl <strong>Die gr\u00f6\u00dften Verbesserungen f\u00fcr FMP k\u00f6nnen durch das Senden von gestalteten Markups in Ihrem erzielt werden <code>index.html<\/code><\/strong>. \u00dcbliche Techniken, um dies zu erreichen, sind Vorrendern und serverseitiges Rendern, die eng miteinander verbunden sind und in erl\u00e4utert werden <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/developers.google.com\/web\/updates\/2019\/02\/rendering-on-the-web\">Rendern im Web<\/a>. Beide Techniken f\u00fchren die Web-App in Node aus und serialisieren das resultierende DOM in HTML. Das serverseitige Rendern erledigt dies pro Anforderung auf der Serverseite, w\u00e4hrend das Vorrendern dies zur Erstellungszeit tut und die Ausgabe als Ihre neue speichert <code>index.html<\/code>. Da ist PROXX ein <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/jamstack.org\/\">JAMStack<\/a> App und hat keine Server-Seite, haben wir beschlossen, Prerendering zu implementieren.<\/p>\n<p>Es gibt viele M\u00f6glichkeiten, einen Prerenderer zu implementieren. In PROXX haben wir uns f\u00fcr die Verwendung entschieden <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/pptr.dev\">Puppenspieler<\/a>Hiermit wird Chrome ohne Benutzeroberfl\u00e4che gestartet und Sie k\u00f6nnen diese Instanz mit einer Node-API fernsteuern. Wir verwenden dies, um unser Markup und unser JavaScript einzuf\u00fcgen und dann das DOM als HTML-Zeichenfolge zur\u00fcckzulesen. Weil wir benutzen <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/github.com\/css-modules\/css-modules\">CSS-Module<\/a>Wir erhalten CSS-Inlining der Stile, die wir kostenlos ben\u00f6tigen.<\/p>\n<p><web-copy-code><\/p>\n<pre class=\"language-js\"><code class=\"language-js\">  <span class=\"token keyword\">const<\/span> Browser <span class=\"token operator\">=<\/span> <span class=\"token keyword\">erwarten<\/span> puppeteer<span class=\"token punctuation\">.<\/span><span class=\"token function\">launch<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token keyword\">const<\/span> Seite <span class=\"token operator\">=<\/span> <span class=\"token keyword\">erwarten<\/span> Browser<span class=\"token punctuation\">.<\/span><span class=\"token function\">newPage<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token keyword\">erwarten<\/span> Seite<span class=\"token punctuation\">.<\/span><span class=\"token function\">setContent<\/span><span class=\"token punctuation\">(<\/span>rawIndexHTML<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token keyword\">erwarten<\/span> Seite<span class=\"token punctuation\">.<\/span><span class=\"token function\">evaluate<\/span><span class=\"token punctuation\">(<\/span>codeToRun<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token keyword\">const<\/span> renderedHTML <span class=\"token operator\">=<\/span> <span class=\"token keyword\">erwarten<\/span> Seite<span class=\"token punctuation\">.<\/span><span class=\"token function\">Inhalt<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br>Browser<span class=\"token punctuation\">.<\/span><span class=\"token function\">close<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token keyword\">erwarten<\/span> <span class=\"token function\">writeFile<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">\"index.html\"<\/span><span class=\"token punctuation\">,<\/span> renderedHTML<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/code><\/pre>\n<p><\/web-copy-code><\/p>\n<p>Damit k\u00f6nnen wir eine Verbesserung f\u00fcr unseren FMP erwarten. Wir m\u00fcssen immer noch die gleiche Menge an JavaScript wie zuvor laden und ausf\u00fchren, daher sollten wir nicht erwarten, dass sich TTI stark \u00e4ndert. Wenn \u00fcberhaupt, unsere <code>index.html<\/code> ist gr\u00f6\u00dfer geworden und k\u00f6nnte unseren TTI etwas zur\u00fcckschieben. Es gibt nur einen Weg, dies herauszufinden: Ausf\u00fchren von WebPageTest.<\/p>\n<figure class=\"w-figure\">\n  <video controls=\"\" muted=\"\" preload=\"metadata\" class=\"w-screenshot\" poster=\"https:\/\/storage.googleapis.com\/web-dev-assets\/js-heavy-sites\/ssr-proxx-load-poster.jpg\" src=\"https:\/\/storage.googleapis.com\/web-dev-assets\/js-heavy-sites\/ssr-proxx-load.mp4\" type=\"video\/mp4; codecs=h264\"><\/video><figcaption class=\"w-figcaption w-figcaption--fullbleed\">\n    Der Filmstreifen zeigt eine deutliche Verbesserung unserer FMP-Metrik. TTI ist meist nicht betroffen.<br \/>\n  <\/figcaption><\/figure>\n<p><strong>Unsere erste aussagekr\u00e4ftige Farbe hat sich von 8,5 Sekunden auf 4,9 Sekunden bewegt.<\/strong> eine massive Verbesserung. Unser TTI liegt immer noch bei etwa 8,5 Sekunden, sodass er von dieser \u00c4nderung weitgehend unber\u00fchrt blieb. Was wir hier gemacht haben, ist a <em>Wahrnehmung<\/em> Ver\u00e4nderung. Einige nennen es vielleicht sogar ein Kunstst\u00fcck. Indem wir ein Zwischenbild des Spiels rendern, \u00e4ndern wir die wahrgenommene Ladeleistung zum Besseren.<\/p>\n<h2 id=\"inlining\"><span class=\"ez-toc-section\" id=\"Inlining\"><\/span>Inlining <span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Eine weitere Metrik, die uns sowohl DevTools als auch WebPageTest geben, ist Time To First Byte (TTFB). Dies ist die Zeit, die vom ersten Byte der gesendeten Anforderung bis zum ersten Byte der empfangenen Antwort ben\u00f6tigt wird. Diese Zeit wird oft auch als Round Trip Time (RTT) bezeichnet, obwohl technisch gesehen ein Unterschied zwischen diesen beiden Zahlen besteht: RTT enth\u00e4lt nicht die Verarbeitungszeit der Anforderung auf der Serverseite. <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/developers.google.com\/web\/tools\/chrome-devtools\/network\/reference#timing-preview\">DevTools<\/a> und WebPageTest visualisieren TTFB mit einer hellen Farbe innerhalb des Anforderungs- \/ Antwortblocks.<\/p>\n<figure class=\"w-figure\">\n  <picture>\n<\/picture><figcaption class=\"w-figcaption\">\n    Der helle Abschnitt einer Anfrage zeigt an, dass die Anfrage auf den Empfang des ersten Bytes der Antwort wartet.<br \/>\n  <\/figcaption><\/figure>\n<p>Wenn wir unseren Wasserfall betrachten, k\u00f6nnen wir sehen, dass die <strong>Alle Anfragen geben die aus <em>Mehrheit<\/em> ihrer Zeit warten<\/strong> f\u00fcr das erste Byte der Antwort ankommen.<\/p>\n<p>F\u00fcr dieses Problem wurde HTTP \/ 2 Push urspr\u00fcnglich konzipiert. Der App-Entwickler <em>wei\u00df<\/em> dass bestimmte Ressourcen ben\u00f6tigt werden und k\u00f6nnen <em>dr\u00fccken<\/em> sie den Draht hinunter. Wenn der Client erkennt, dass er zus\u00e4tzliche Ressourcen abrufen muss, befinden sie sich bereits in den Caches des Browsers. <strong>HTTP \/ 2 Push erwies sich als zu schwierig, um es richtig zu machen, und wird als entmutigt angesehen.<\/strong> Dieser Problembereich wird w\u00e4hrend der Standardisierung von HTTP \/ 3 erneut \u00fcberpr\u00fcft. Zur Zeit, <strong>Die einfachste L\u00f6sung ist zu <em>im Einklang<\/em> alle kritischen Ressourcen<\/strong> auf Kosten der Caching-Effizienz.<\/p>\n<p>Unser kritisches CSS ist dank CSS-Modulen und unserem Puppenspieler-basierten Prerenderer bereits integriert. F\u00fcr JavaScript m\u00fcssen wir unsere kritischen Module einbinden <em>und ihre Abh\u00e4ngigkeiten<\/em>. Diese Aufgabe hat je nach verwendetem Bundler unterschiedliche Schwierigkeiten.<\/p>\n<div class=\"w-aside w-aside--note\">\n<p><strong>Hinweis:<\/strong> In diesem Schritt setzen wir unsere Schriftdateien auch so ein, dass sie nur die Glyphen enthalten, die wir f\u00fcr unsere Zielseite ben\u00f6tigen. Ich werde auf diesen Schritt nicht n\u00e4her eingehen, da er nicht leicht zu abstrahieren und manchmal nicht einmal praktisch ist. Wir laden die vollst\u00e4ndigen Schriftdateien immer noch tr\u00e4ge, aber sie werden f\u00fcr das anf\u00e4ngliche Rendern nicht ben\u00f6tigt.<\/p>\n<\/div>\n<figure class=\"w-figure\">\n  <video controls=\"\" muted=\"\" preload=\"metadata\" class=\"w-screenshot\" poster=\"https:\/\/storage.googleapis.com\/web-dev-assets\/js-heavy-sites\/ssr-proxx-load-poster.jpg\" src=\"https:\/\/storage.googleapis.com\/web-dev-assets\/js-heavy-sites\/ssr-proxx-load.mp4\" type=\"video\/mp4; codecs=h264\"><\/video><figcaption class=\"w-figcaption w-figcaption--fullbleed\">\n    Mit dem Inlining unseres JavaScript haben wir unseren TTI von 8,5 auf 7,2 Sekunden reduziert.<br \/>\n  <\/figcaption><\/figure>\n<p>Dies hat unseren TTI um 1 Sekunde verk\u00fcrzt. Wir haben jetzt den Punkt erreicht, an dem unsere <code>index.html<\/code> enth\u00e4lt alles, was f\u00fcr das anf\u00e4ngliche Rendern und Interaktivieren ben\u00f6tigt wird. Der HTML-Code kann gerendert werden, w\u00e4hrend er noch heruntergeladen wird, wodurch unser FMP erstellt wird. Sobald der HTML-Code analysiert und ausgef\u00fchrt wurde, ist die App interaktiv.<\/p>\n<h2 id=\"aggressive-code-splitting\"><span class=\"ez-toc-section\" id=\"Aggressive-code-splitting\"><\/span>Aggressive Code-Aufteilung <span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Ja, unsere <code>index.html<\/code> enth\u00e4lt alles, was ben\u00f6tigt wird, um interaktiv zu werden. Bei n\u00e4herer Betrachtung stellt sich jedoch heraus, dass es auch alles andere enth\u00e4lt. Unsere <code>index.html<\/code> ist ungef\u00e4hr 43 KB. Lassen Sie uns dies in Bezug auf das setzen, mit dem der Benutzer zu Beginn interagieren kann: Wir haben ein Formular zum Konfigurieren des Spiels, das einige Komponenten, eine Startschaltfl\u00e4che und wahrscheinlich Code zum Beibehalten und Laden von Benutzereinstellungen enth\u00e4lt. Das wars so ziemlich. 43 KB scheinen viel zu sein.<\/p>\n<figure class=\"w-figure\">\n  <picture><source srcset=\"https:\/\/web.dev\/proxx-loaded.webp\" type=\"image\/webp\"><img alt='proxx-geladen-1500619' src='https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/proxx-loaded-1500619.jpg'><br \/>\n  <\/source><\/picture><figcaption class=\"w-figcaption\">\n    Die Landingpage von PROXX. Hier werden nur kritische Komponenten verwendet.<br \/>\n  <\/figcaption><\/figure>\n<p>Um zu verstehen, woher unsere Bundle-Gr\u00f6\u00dfe kommt, k\u00f6nnen wir a verwenden <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/npm.im\/source-map-explorer\">Quellkarten-Explorer<\/a> or a equivalente tool to break down what the bundle consists of. As predicted, our bundle contains the game logic, the rendering engine, the win screen, the lose screen and a bunch of utilities. Only a small subset of these modules are needed for the landing page. Moving everything that is not strictly required for interactivity into a lazily-loaded module will decrease TTI <em>bedeutend<\/em>.<\/p>\n<figure class=\"w-figure\">\n  <picture>\n<\/picture><figcaption class=\"w-figcaption\">\n    Die Analyse des Inhalts der PROXX-Datei &quot;index.html&quot; zeigt viele nicht ben\u00f6tigte Ressourcen. Kritische Ressourcen werden hervorgehoben.<br \/>\n  <\/figcaption><\/figure>\n<p>Was wir tun m\u00fcssen, ist Code-Split. Durch das Aufteilen von Code wird Ihr monolithisches B\u00fcndel in kleinere Teile zerlegt, die bei Bedarf faul geladen werden k\u00f6nnen. Beliebte Bundler m\u00f6gen <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/webpack.js.org\">Webpack<\/a>, <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/rollupjs.org\">Aufrollen<\/a>, und <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/parceljs.org\">Paket<\/a> Unterst\u00fctzung der Code-Aufteilung mithilfe von Dynamic <code>importieren ()<\/code>. Der Bundler analysiert Ihren Code und <em>im Einklang<\/em> alle Module, die importiert werden <em>statisch<\/em>. Alles, was Sie importieren <em>dynamisch<\/em> wird in eine eigene Datei gestellt und erst dann aus dem Netzwerk abgerufen, wenn die <code>importieren ()<\/code> Aufruf wird ausgef\u00fchrt. Nat\u00fcrlich ist das Erreichen des Netzwerks mit Kosten verbunden und sollte nur durchgef\u00fchrt werden, wenn Sie Zeit haben. <strong>Das Mantra hier besteht darin, die vorhandenen Module statisch zu importieren <em>kritisch<\/em> ben\u00f6tigt zum Ladezeitpunkt und l\u00e4dt dynamisch alles andere.<\/strong> Sie sollten jedoch nicht bis zum letzten Moment warten, um Module zu laden, die definitiv verwendet werden. <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/twitter.com\/philwalton\">Phil Walton<\/a>&#039;s <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/philipwalton.com\/articles\/idle-until-urgent\/\">Leerlauf bis dringend<\/a> ist ein gro\u00dfartiges Muster f\u00fcr einen gesunden Mittelweg zwischen faulem Laden und eifrigem Laden.<\/p>\n<p>In PROXX haben wir eine erstellt <code>faul.js<\/code> Datei, die statisch alles importiert, was wir <em>Nein<\/em> brauchen. In unserer Hauptdatei k\u00f6nnen wir dann <em>dynamisch<\/em> importieren <code>faul.js<\/code>. Einige unserer <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/preactjs.com\">Vorbereiten<\/a> Komponenten endeten in <code>faul.js<\/code>Dies stellte sich als etwas kompliziert heraus, da Preact nicht mit faul geladenen Komponenten sofort umgehen kann. Aus diesem Grund haben wir ein wenig geschrieben <code>aufgeschoben<\/code> Komponenten-Wrapper, mit dem wir einen Platzhalter rendern k\u00f6nnen, bis die eigentliche Komponente geladen wurde.<\/p>\n<p><web-copy-code><\/p>\n<pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">Export<\/span> <span class=\"token keyword\">Standard<\/span> <span class=\"token keyword\">Funktion<\/span> <span class=\"token function\">aufgeschoben<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">componentPromise<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br><span class=\"token keyword\">R\u00fcckkehr<\/span> <span class=\"token keyword\">Klasse<\/span> <span class=\"token class-name\">Deferred<\/span> <span class=\"token keyword\">extends<\/span> <span class=\"token class-name\">Component<\/span> <span class=\"token punctuation\">{<\/span><br><span class=\"token function\">Baumeister<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">props<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br><span class=\"token keyword\">super<\/span><span class=\"token punctuation\">(<\/span>props<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token keyword\">Este<\/span><span class=\"token punctuation\">.<\/span>Zustand <span class=\"token operator\">=<\/span> <span class=\"token punctuation\">{<\/span><br>LoadedComponent<span class=\"token operator\">:<\/span> <span class=\"token keyword\">nicht definiert<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><br>componentPromise<span class=\"token punctuation\">.<\/span><span class=\"token function\">then<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">component<\/span> <span class=\"token operator\">=&gt;<\/span> <span class=\"token punctuation\">{<\/span><br><span class=\"token keyword\">Este<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">setState<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span> LoadedComponent<span class=\"token operator\">:<\/span> component <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token punctuation\">}<\/span><p><span class=\"token function\">render<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\"><span class=\"token punctuation\">{<\/span> loaded<span class=\"token punctuation\">,<\/span> Wird geladen <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span> LoadedComponent <span class=\"token punctuation\">}<\/span><\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br><span class=\"token keyword\">wenn<\/span> <span class=\"token punctuation\">(<\/span>LoadedComponent<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br><span class=\"token keyword\">R\u00fcckkehr<\/span> <span class=\"token function\">loaded<\/span><span class=\"token punctuation\">(<\/span>LoadedComponent<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token punctuation\">}<\/span><br><span class=\"token keyword\">R\u00fcckkehr<\/span> <span class=\"token function\">Wird geladen<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token punctuation\">}<\/span><br><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><br><span class=\"token punctuation\">}<\/span><\/p><\/code><\/pre>\n<p><\/web-copy-code><\/p>\n<p>Wenn dies vorhanden ist, k\u00f6nnen wir ein Versprechen einer Komponente in unserem verwenden <code>render ()<\/code> Funktionen. Zum Beispiel die <code><\/code> Komponente, die das animierte Hintergrundbild rendert, wird durch eine leere ersetzt <code>&lt;div&gt;<\/code> w\u00e4hrend die Komponente geladen wird. Sobald die Komponente geladen und einsatzbereit ist, wird die <code>&lt;div&gt;<\/code> wird durch die eigentliche Komponente ersetzt.<\/p>\n<p><web-copy-code><\/p>\n<pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const<\/span> NebulaDeferred <span class=\"token operator\">=<\/span> <span class=\"token function\">aufgeschoben<\/span><span class=\"token punctuation\">(<\/span><br><span class=\"token keyword\">importieren<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">\"\/components\/nebula\"<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">then<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">m<\/span> <span class=\"token operator\">=&gt;<\/span> m<span class=\"token punctuation\">.<\/span>Standard<span class=\"token punctuation\">)<\/span><br><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><p><span class=\"token keyword\">R\u00fcckkehr<\/span> <span class=\"token punctuation\">(<\/span><br><span class=\"token operator\">&lt;<\/span>NebulaDeferred<br>Wird geladen<span class=\"token operator\">=<\/span><span class=\"token punctuation\">{<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=&gt;<\/span> <span class=\"token operator\">&lt;<\/span>div <span class=\"token operator\">\/<\/span><span class=\"token operator\">&gt;<\/span><span class=\"token punctuation\">}<\/span><br>loaded<span class=\"token operator\">=<\/span><span class=\"token punctuation\">{<\/span><span class=\"token parameter\">Nebula<\/span> <span class=\"token operator\">=&gt;<\/span> <span class=\"token operator\">&lt;<\/span>Nebula <span class=\"token operator\">\/<\/span><span class=\"token operator\">&gt;<\/span><span class=\"token punctuation\">}<\/span><br><span class=\"token operator\">\/<\/span><span class=\"token operator\">&gt;<\/span><br><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p><\/code><\/pre>\n<p><\/web-copy-code><\/p>\n<p>Mit all dem haben wir unsere reduziert <code>index.html<\/code> auf nur 20 KB, weniger als die H\u00e4lfte der Originalgr\u00f6\u00dfe. Wie wirkt sich das auf FMP und TTI aus? WebPageTest wird es zeigen!<\/p>\n<figure class=\"w-figure\">\n  <video controls=\"\" muted=\"\" preload=\"metadata\" class=\"w-screenshot\" poster=\"https:\/\/storage.googleapis.com\/web-dev-assets\/js-heavy-sites\/optimized-proxx-load-poster.jpg\" src=\"https:\/\/storage.googleapis.com\/web-dev-assets\/js-heavy-sites\/optimized-proxx-load.mp4\" type=\"video\/mp4; codecs=h264\"><\/video><figcaption class=\"w-figcaption w-figcaption--fullbleed\">\n    Der Filmstreifen best\u00e4tigt: Unser TTI liegt jetzt bei 5,4 Sekunden. Eine drastische Verbesserung gegen\u00fcber unseren urspr\u00fcnglichen 11ern.<br \/>\n  <\/figcaption><\/figure>\n<p>Unser FMP und TTI sind nur 100 ms voneinander entfernt, da es nur darum geht, das inline-JavaScript zu analysieren und auszuf\u00fchren. Nach nur 5,4 Sekunden auf 2G ist die App vollst\u00e4ndig interaktiv. Alle anderen, weniger wichtigen Module werden im Hintergrund geladen.<\/p>\n<h2 id=\"more-sleight-of-hand\"><span class=\"ez-toc-section\" id=\"More-Sleight-of-Hand\"><\/span>Mehr Fingerspitzengef\u00fchl <span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Wenn Sie sich unsere Liste der kritischen Module oben ansehen, werden Sie feststellen, dass die Rendering-Engine nicht Teil der kritischen Module ist. Nat\u00fcrlich kann das Spiel erst gestartet werden, wenn wir unsere Rendering-Engine haben, um das Spiel zu rendern. Wir k\u00f6nnten die Schaltfl\u00e4che \u00abStart\u00bb deaktivieren, bis unsere Rendering-Engine zum Starten des Spiels bereit ist. Nach unserer Erfahrung ben\u00f6tigt der Benutzer jedoch normalerweise lange genug, um seine Spieleinstellungen so zu konfigurieren, dass dies nicht erforderlich ist. Meistens werden die Rendering-Engine und die anderen verbleibenden Module geladen, wenn der Benutzer \u00abStart\u00bb dr\u00fcckt. In dem seltenen Fall, dass der Benutzer schneller als seine Netzwerkverbindung ist, wird ein einfacher Ladebildschirm angezeigt, der darauf wartet, dass die verbleibenden Module fertig sind.<\/p>\n<h2 id=\"conclusion\"><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span>Fazit <span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Messen ist wichtig. Um zu vermeiden, dass Sie sich mit Problemen befassen, die nicht real sind, empfehlen wir, immer zuerst zu messen, bevor Sie Optimierungen implementieren. Zus\u00e4tzlich sollten Messungen am durchgef\u00fchrt werden <em>echt<\/em> Ger\u00e4te an einer 3G-Verbindung oder an <a rel=\"nofollow noopener noreferrer\" target=\"_blank\" href=\"https:\/\/webpagetest.org\/easy\">WebPageTest<\/a> wenn kein echtes Ger\u00e4t zur Hand ist.<\/p>\n<p>Der Filmstreifen kann einen Einblick in das Laden Ihrer App geben <em>f\u00fchlt sich<\/em> f\u00fcr den Benutzer. Der Wasserfall kann Ihnen sagen, welche Ressourcen f\u00fcr m\u00f6glicherweise lange Ladezeiten verantwortlich sind. Hier ist eine Checkliste mit Ma\u00dfnahmen, mit denen Sie die Ladeleistung verbessern k\u00f6nnen:<\/p>\n<ul>\n<li>Stellen Sie so viele Assets wie m\u00f6glich \u00fcber eine Verbindung bereit.<\/li>\n<li>Laden Sie Ressourcen vor oder sogar inline, die f\u00fcr das erste Rendern und die erste Interaktivit\u00e4t erforderlich sind.<\/li>\n<li>Rendern Sie Ihre App vor, um die wahrgenommene Ladeleistung zu verbessern.<\/li>\n<li>Nutzen Sie die aggressive Codeaufteilung, um die f\u00fcr die Interaktivit\u00e4t erforderliche Codemenge zu reduzieren.<\/li>\n<\/ul>\n<p>Seien Sie gespannt auf Teil 2, in dem wir diskutieren, wie Sie die Laufzeitleistung auf Ger\u00e4ten mit eingeschr\u00e4nkten Bedingungen optimieren k\u00f6nnen.<\/p>\n<p>    <web-feedback additional-questions=\"\"><\/web-feedback>\n  <\/div>\n<p><script async src=\"\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script><\/p>","protected":false},"excerpt":{"rendered":"<p>How we used code splitting, code inlining, and server-side rendering in PROXX. Sep 23, 2019 At Google I\/O 2019 Mariko, Jake, and I shipped PROXX, a modern Minesweeper-clone for the&#8230;<\/p>","protected":false},"author":1,"featured_media":83277,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1356],"tags":[],"class_list":["post-83276","post","type-post","status-publish","format-standard","has-post-thumbnail","category-dev"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.0 (Yoast SEO v28.2) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Techniques to make a web app load fast, even on a feature phone - R Marketing Digital<\/title>\n<meta name=\"description\" content=\"How we used code splitting, code inlining, and server-side rendering in PROXX. Sep 23, 2019 At Google I\/O 2019 Mariko, Jake, and I shipped PROXX, a modern\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/rmarketingdigital.com\/de\/dev\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Techniques to make a web app load fast, even on a feature phone\" \/>\n<meta property=\"og:description\" content=\"How we used code splitting, code inlining, and server-side rendering in PROXX. Sep 23, 2019 At Google I\/O 2019 Mariko, Jake, and I shipped PROXX, a modern\" \/>\n<meta property=\"og:url\" content=\"https:\/\/rmarketingdigital.com\/de\/dev\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\/\" \/>\n<meta property=\"og:site_name\" content=\"R Marketing Digital\" \/>\n<meta property=\"article:published_time\" content=\"2022-08-04T05:47:54+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/hero-4373669.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"600\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"R Marketing Digital\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/de\\\/dev\\\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/de\\\/dev\\\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\\\/\"},\"author\":{\"name\":\"R Marketing Digital\",\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/#\\\/schema\\\/person\\\/7c0d9782b2977b840b3740f00c69a73e\"},\"headline\":\"Techniques to make a web app load fast, even on a feature phone\",\"datePublished\":\"2022-08-04T05:47:54+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/de\\\/dev\\\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\\\/\"},\"wordCount\":2831,\"image\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/de\\\/dev\\\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/rmarketingdigital.com\\\/wp-content\\\/uploads\\\/2020\\\/09\\\/hero-4373669.jpg\",\"articleSection\":[\"Dev\"],\"inLanguage\":\"de\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/de\\\/dev\\\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\\\/\",\"url\":\"https:\\\/\\\/rmarketingdigital.com\\\/de\\\/dev\\\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\\\/\",\"name\":\"Techniques to make a web app load fast, even on a feature phone - R Marketing Digital\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/de\\\/dev\\\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/de\\\/dev\\\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/rmarketingdigital.com\\\/wp-content\\\/uploads\\\/2020\\\/09\\\/hero-4373669.jpg\",\"datePublished\":\"2022-08-04T05:47:54+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/#\\\/schema\\\/person\\\/7c0d9782b2977b840b3740f00c69a73e\"},\"description\":\"How we used code splitting, code inlining, and server-side rendering in PROXX. Sep 23, 2019 At Google I\\\/O 2019 Mariko, Jake, and I shipped PROXX, a modern\",\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/rmarketingdigital.com\\\/de\\\/dev\\\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/de\\\/dev\\\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\\\/#primaryimage\",\"url\":\"https:\\\/\\\/rmarketingdigital.com\\\/wp-content\\\/uploads\\\/2020\\\/09\\\/hero-4373669.jpg\",\"contentUrl\":\"https:\\\/\\\/rmarketingdigital.com\\\/wp-content\\\/uploads\\\/2020\\\/09\\\/hero-4373669.jpg\",\"width\":1200,\"height\":600,\"caption\":\"hero-4373669-1498311-jpg\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/#website\",\"url\":\"https:\\\/\\\/rmarketingdigital.com\\\/\",\"name\":\"R Marketing Digital\",\"description\":\"Agencia SEO | Publicidad redes sociales | Community Management\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/rmarketingdigital.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/rmarketingdigital.com\\\/#\\\/schema\\\/person\\\/7c0d9782b2977b840b3740f00c69a73e\",\"name\":\"R Marketing Digital\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c5599c203e0120b8ccbff4666af86f35f9b3dcad468a8bc6295313a3964a80be?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c5599c203e0120b8ccbff4666af86f35f9b3dcad468a8bc6295313a3964a80be?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c5599c203e0120b8ccbff4666af86f35f9b3dcad468a8bc6295313a3964a80be?s=96&d=mm&r=g\",\"caption\":\"R Marketing Digital\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Techniques to make a web app load fast, even on a feature phone - R Marketing Digital","description":"Wie wir Code-Splitting, Code-Inlining und serverseitiges Rendern in PROXX verwendet haben. 23. September 2019 Bei Google I \/ O 2019 haben Mariko, Jake und ich PROXX ausgeliefert, eine moderne","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/rmarketingdigital.com\/de\/dev\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\/","og_locale":"de_DE","og_type":"article","og_title":"Techniques to make a web app load fast, even on a feature phone","og_description":"How we used code splitting, code inlining, and server-side rendering in PROXX. Sep 23, 2019 At Google I\/O 2019 Mariko, Jake, and I shipped PROXX, a modern","og_url":"https:\/\/rmarketingdigital.com\/de\/dev\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\/","og_site_name":"R Marketing Digital","article_published_time":"2022-08-04T05:47:54+00:00","og_image":[{"width":1200,"height":600,"url":"https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/hero-4373669.jpg","type":"image\/jpeg"}],"author":"R Marketing Digital","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/rmarketingdigital.com\/de\/dev\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\/#article","isPartOf":{"@id":"https:\/\/rmarketingdigital.com\/de\/dev\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\/"},"author":{"name":"R Marketing Digital","@id":"https:\/\/rmarketingdigital.com\/#\/schema\/person\/7c0d9782b2977b840b3740f00c69a73e"},"headline":"Techniques to make a web app load fast, even on a feature phone","datePublished":"2022-08-04T05:47:54+00:00","mainEntityOfPage":{"@id":"https:\/\/rmarketingdigital.com\/de\/dev\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\/"},"wordCount":2831,"image":{"@id":"https:\/\/rmarketingdigital.com\/de\/dev\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\/#primaryimage"},"thumbnailUrl":"https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/hero-4373669.jpg","articleSection":["Dev"],"inLanguage":"de"},{"@type":"WebPage","@id":"https:\/\/rmarketingdigital.com\/de\/dev\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\/","url":"https:\/\/rmarketingdigital.com\/de\/dev\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\/","name":"Techniques to make a web app load fast, even on a feature phone - R Marketing Digital","isPartOf":{"@id":"https:\/\/rmarketingdigital.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/rmarketingdigital.com\/de\/dev\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\/#primaryimage"},"image":{"@id":"https:\/\/rmarketingdigital.com\/de\/dev\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\/#primaryimage"},"thumbnailUrl":"https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/hero-4373669.jpg","datePublished":"2022-08-04T05:47:54+00:00","author":{"@id":"https:\/\/rmarketingdigital.com\/#\/schema\/person\/7c0d9782b2977b840b3740f00c69a73e"},"description":"Wie wir Code-Splitting, Code-Inlining und serverseitiges Rendern in PROXX verwendet haben. 23. September 2019 Bei Google I \/ O 2019 haben Mariko, Jake und ich PROXX ausgeliefert, eine moderne","inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/rmarketingdigital.com\/de\/dev\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/rmarketingdigital.com\/de\/dev\/techniken-mit-denen-eine-web-app-schnell-und-sogar-auf-einem-feature-telefon-geladen-werden-kann\/#primaryimage","url":"https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/hero-4373669.jpg","contentUrl":"https:\/\/rmarketingdigital.com\/wp-content\/uploads\/2020\/09\/hero-4373669.jpg","width":1200,"height":600,"caption":"hero-4373669-1498311-jpg"},{"@type":"WebSite","@id":"https:\/\/rmarketingdigital.com\/#website","url":"https:\/\/rmarketingdigital.com\/","name":"R Digitales Marketing","description":"SEO Agentur | Werbung f\u00fcr soziale Netzwerke | Community Management","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/rmarketingdigital.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Person","@id":"https:\/\/rmarketingdigital.com\/#\/schema\/person\/7c0d9782b2977b840b3740f00c69a73e","name":"R Digitales Marketing","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/c5599c203e0120b8ccbff4666af86f35f9b3dcad468a8bc6295313a3964a80be?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/c5599c203e0120b8ccbff4666af86f35f9b3dcad468a8bc6295313a3964a80be?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/c5599c203e0120b8ccbff4666af86f35f9b3dcad468a8bc6295313a3964a80be?s=96&d=mm&r=g","caption":"R Marketing Digital"}}]}},"_links":{"self":[{"href":"https:\/\/rmarketingdigital.com\/de\/wp-json\/wp\/v2\/posts\/83276","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rmarketingdigital.com\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rmarketingdigital.com\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rmarketingdigital.com\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rmarketingdigital.com\/de\/wp-json\/wp\/v2\/comments?post=83276"}],"version-history":[{"count":0,"href":"https:\/\/rmarketingdigital.com\/de\/wp-json\/wp\/v2\/posts\/83276\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rmarketingdigital.com\/de\/wp-json\/wp\/v2\/media\/83277"}],"wp:attachment":[{"href":"https:\/\/rmarketingdigital.com\/de\/wp-json\/wp\/v2\/media?parent=83276"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rmarketingdigital.com\/de\/wp-json\/wp\/v2\/categories?post=83276"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rmarketingdigital.com\/de\/wp-json\/wp\/v2\/tags?post=83276"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}