{"id":68644,"date":"2019-07-30T04:18:04","date_gmt":"2019-07-30T11:18:04","guid":{"rendered":"http:\/\/www.taterboy.com\/blog\/2019\/07\/i-used-the-web-for-a-day-on-a-50-mb-budget\/"},"modified":"2019-07-30T04:18:04","modified_gmt":"2019-07-30T11:18:04","slug":"i-used-the-web-for-a-day-on-a-50-mb-budget","status":"publish","type":"post","link":"https:\/\/www.taterboy.com\/blog\/2019\/07\/i-used-the-web-for-a-day-on-a-50-mb-budget\/","title":{"rendered":"I Used The Web For A Day On A 50 MB Budget"},"content":{"rendered":"<link rel=\"canonical\" href=\"https:\/\/www.smashingmagazine.com\/2019\/07\/web-on-50mb-budget\/\"><title>I Used The Web For A Day On A 50 MB Budget<\/title><\/p>\n<article>\n<header>\n<h1>I Used The Web For A Day On A 50 MB Budget<\/h1>\n<address>Chris Ashton<\/address>\n<p>                  <time datetime=\"2019-07-29T14:00:59+02:00\">2019-07-29T14:00:59+02:00<\/time><time datetime=\"2019-07-30T11:06:47+00:00\">2019-07-30T11:06:47+00:00<\/time><\/header>\n<p>This article is part of a series in which I attempt to use the web under various constraints, representing a given demographic of user. I hope to raise the profile of difficulties faced by real people, which are avoidable if we design and develop in a way that is sympathetic to their needs.<\/p>\n<p>Last time, I <a href=\"https:\/\/www.smashingmagazine.com\/2019\/03\/web-on-internet-explorer-ie8\/\">navigated the web for a day using Internet Explorer 8<\/a>. This time, I browsed the web for a day on a 50 MB budget.<\/p>\n<h3>Why 50 MB?<\/h3>\n<p>Many of us are lucky enough to be on mobile plans which allow several gigabytes of data transfer per month. Failing that, we are usually able to connect to home or public WiFi networks that are on fast broadband connections and have effectively unlimited data.<\/p>\n<p>But there are parts of the world where mobile data is prohibitively expensive, and where there is little or no broadband infrastructure.<\/p>\n<blockquote>\n<p>People often buy data packages of just tens of megabytes at a time, making a gigabyte a relatively large and therefore expensive amount of data to buy.<br \/>\u2014 Dan Howdle, consumer telecoms analyst at Cable.co.uk<\/p>\n<\/blockquote>\n<p>Just how expensive are we talking?<\/p>\n<div data-component=\"FeaturePanel\" data-audience=\"non-subscriber\" data-remove=\"true\"><\/div>\n<h4>The Cost Of Mobile Data<\/h4>\n<p>A 2018\u00a0<a href=\"https:\/\/www.cable.co.uk\/mobiles\/worldwide-data-pricing\/\">study by cable.co.uk<\/a>\u00a0found that Zimbabwe was the most expensive country in the world for mobile data, where 1 GB cost an average of $75.20, ranging from $12.50 to $138.46. The enormous range in price is due to smaller amounts of data being <em>very<\/em> expensive, getting proportionally cheaper the bigger the data plan you commit to. You can read the\u00a0<a href=\"https:\/\/s3-eu-west-1.amazonaws.com\/assets.cable.co.uk\/mobile-data-cost\/cost-of-a-gigabyte-research-method.pdf\">study methodology<\/a>\u00a0for more information.<\/p>\n<p>Zimbabwe is by no means a one-off.\u00a0Equatorial Guinea, Saint Helena and the Falkland Islands are next in line, with 1 GB of data costing $65.83, $55.47 and $47.39 respectively. These countries generally have a combination of poor technical infrastructure and low adoption, meaning data is both costly to deliver and doesn\u2019t have the economy of scale to drive costs down.<\/p>\n<p>Data is expensive in parts of Europe too. A gigabyte of data in Greece will set you back $32.71; in Switzerland, $20.22. For comparison, the same amount of data costs $6.66 in the UK, or $12.37 in the USA. On the other end of the scale, India is the cheapest place in the world for data, at an average cost of $0.26. Kyrgyzstan, Kazakhstan and Ukraine follow at $0.27, $0.49 and $0.51 per GB respectively.<\/p>\n<p>The speed of mobile networks, too, varies considerably between countries.\u00a0Perhaps surprisingly, <a href=\"https:\/\/www.opensignal.com\/sites\/opensignal-com\/files\/data\/reports\/global\/data-2018-11\/state_of_wifi_vs_mobile_opensignal_201811.pdf\">users experience faster speeds over a mobile network than WiFi<\/a> in at least 30 countries worldwide, including Australia and France. South Korea has the <a href=\"https:\/\/www.opensignal.com\/sites\/opensignal-com\/files\/data\/reports\/global\/data-2019-05\/the_state_of_mobile_experience_may_2019_0.pdf\">fastest mobile download speed<\/a>, averaging 52.4 Mbps, but Iraq has the slowest, averaging 1.6 Mbps download and 0.7 Mbps upload. The USA ranks 40th in the world for mobile download speeds, at around 34 Mbps, and is\u00a0<a href=\"https:\/\/www.vox.com\/recode\/2019\/7\/12\/20681214\/mobile-speeds-slow-ookla-5g\">at risk of falling further behind<\/a>\u00a0as the world moves towards 5G.<\/p>\n<p>As for mobile network connection type, 84.7% of user connections in the UK are on 4G, compared to 93% in the USA, and 97.5% in South Korea. This compares with less than 50% in Uzbekistan and less than 60% in Algeria, Ecuador, Nepal and Iraq.<\/p>\n<h4>The Cost Of Broadband Data<\/h4>\n<p>Meanwhile, a\u00a0<a href=\"https:\/\/www.cable.co.uk\/broadband\/pricing\/worldwide-comparison\/\">study of the cost of broadband in 2018<\/a>\u00a0shows that a broadband connection in Niger costs $263 \u2018per megabit per month\u2019. This metric is a little difficult to comprehend, so here\u2019s an example: if the average cost of broadband packages in a country is $22, and the average download speed offered by the packages is 10 Mbps, then the cost \u2018per megabit per month\u2019\u00a0 would be $2.20.<\/p>\n<p>It\u2019s an interesting metric, and one that acknowledges that broadband speed is as important a factor as the data cap. A cost of $263 suggests a combination of extremely slow and extremely expensive broadband. For reference, the metric is $1.19 in the UK and $1.26 in the USA.<\/p>\n<p>What\u2019s perhaps easier to comprehend is the average cost of a broadband package. Note that this study was looking for the cheapest broadband packages on offer, ignoring whether or not these packages had a data cap, so provides a useful ballpark figure rather than the cost of data per se.<\/p>\n<p>On package cost alone, Mauritania has the most expensive broadband in the world, at an average of $768.16 (a range of $307.26 to $1,368.72).\u00a0This enormous cost includes building physical lines to the property, since few already exist in Mauritania. At 0.7 Mbps, Mauritania also has one of the slowest broadband networks in the world.<\/p>\n<p><a href=\"https:\/\/www.cable.co.uk\/broadband\/speed\/worldwide-speed-league\/\">Taiwan has the fastest broadband in the world<\/a>, at a mean speed of 85 Mbps. Yemen has the slowest, at 0.38 Mbps. But even countries with good established broadband infrastructure have so-called \u2018not-spots\u2019. The United Kingdom is ranked 34th out of 207 countries for broadband speed, but in July 2019 there was\u00a0<a href=\"https:\/\/www.bbc.co.uk\/news\/uk-wales-48982460\">still a school in the UK without broadband<\/a>.<\/p>\n<p>The average cost of a broadband package in the UK\u00a0is $39.58, and in the USA is $67.69. The cheapest average in the world is Ukraine\u2019s, at just $5, although the cheapest broadband deal of them all was found in Kyrgystan ($1.27 \u2014 against the country average of $108.22).<\/p>\n<p>Zimbabwe was the most costly country for mobile data, and the statistics aren\u2019t much better for its broadband, with an average cost of $128.71 and a \u2018per megabit per month\u2019 cost of $6.89.<\/p>\n<h4>Absolute Cost vs Cost In Real Terms<\/h4>\n<p>All of the costs outlined so far are the absolute costs in USD, based on the exchange rates at the time of the study. These costs\u00a0have\u00a0<a href=\"https:\/\/twitter.com\/ChrisBAshton\/status\/1138726856872607744\">not been accounted for cost of living<\/a>, meaning that for many countries the cost is actually far higher in real terms.<\/p>\n<p>I\u2019m going to limit my browsing today to 50 MB, which in Zimbabwe would cost around $3.67 on a mobile data tariff. That may not sound like much, but teachers in Zimbabwe were striking this year because their <a href=\"https:\/\/www.timeslive.co.za\/news\/africa\/2019-02-06-striking-zimbabwean-teachers-earn-equivalent-of-just-r700-a-month\/\">salaries had fallen to just $2.50 a day<\/a>.<\/p>\n<p>For comparison, $3.67 is around half the <a href=\"https:\/\/www.dol.gov\/general\/topic\/wages\/minimumwage\">$7.25 minimum wage in the USA<\/a>. As a Zimbabwean, I\u2019d have to work for around a day and a half to earn the money to buy this 50MB data, compared to just half an hour in the USA. It\u2019s not easy to compare cost of living between countries, but on wages alone the $3.67 cost of 50 MB of data in Zimbabwe would feel like $52 to an American on minimum wage.<\/p>\n<h3>Setting Up The Experiment<\/h3>\n<p>I launched Chrome and opened the dev tools, where I throttled the network to a slow 3G connection. I wanted to simulate a slow connection like those experienced by users in Uzbekistan, to see what kind of experience websites would give me. I also throttled my CPU to simulate being on a lower end device.<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/491b7575-818f-4517-acf1-fd209a44aa74\/01-i-used-the-web-for-a-day-on-a-50-mb-budget.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/01-i-used-the-web-for-a-day-on-a-50-mb-budget.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/491b7575-818f-4517-acf1-fd209a44aa74\/01-i-used-the-web-for-a-day-on-a-50-mb-budget.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/491b7575-818f-4517-acf1-fd209a44aa74\/01-i-used-the-web-for-a-day-on-a-50-mb-budget.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/491b7575-818f-4517-acf1-fd209a44aa74\/01-i-used-the-web-for-a-day-on-a-50-mb-budget.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/491b7575-818f-4517-acf1-fd209a44aa74\/01-i-used-the-web-for-a-day-on-a-50-mb-budget.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/01-i-used-the-web-for-a-day-on-a-50-mb-budget.png?w=900\" sizes=\"100vw\" alt=\"\"><\/a><figcaption>\n      I opted to throttle my network to Slow 3G and my CPU to 6x slowdown. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/491b7575-818f-4517-acf1-fd209a44aa74\/01-i-used-the-web-for-a-day-on-a-50-mb-budget.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>I installed <a href=\"https:\/\/chrome.google.com\/webstore\/detail\/modheader\/idgpnmonknjnojddfkpgkljpfnnfcklj\">ModHeader<\/a> and set the <a href=\"https:\/\/developers.google.com\/web\/fundamentals\/performance\/optimizing-content-efficiency\/save-data\/\">\u2018Save-Data\u2019 header<\/a> to let websites know I want to minimise my data usage. This is also the header set by Chrome for Android\u2019s \u2018Lite mode\u2019, which I\u2019ll cover in more detail later.<\/p>\n<p>I downloaded <a href=\"https:\/\/www.tripmode.ch\/\">TripMode<\/a>; an application for Mac which gives you control over which apps on your Mac can access the internet. Any other application\u2019s internet access is automatically blocked.<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/trip-mode.png\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/trip-mode.png?resize=481%2C638\" width=\"481\" height=\"638\" alt=\"Screenshot of Tripmode settings; Chrome is enabled, Mail is disabled\"><\/a><figcaption>You can enable\/disable individual apps from connecting to the internet with TripMode. I enabled Chrome. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/58e4e027-f544-4068-9c0f-47a717885bc9\/screenshot-of-tripmode-settings-chrome-is-enabled-mail-is-disabled.png\">Large preview<\/a>)<\/figcaption><\/figure>\n<p>How far do I predict my 50 MB budget will take me? With the\u00a0<a href=\"https:\/\/httparchive.org\/reports\/page-weight\">average weight of a web page being almost 1.7 MB<\/a>, that suggests I\u2019ve got around 29 pages in my budget, although probably a few more than that if I\u2019m able to stay on the same sites and leverage browser caching.<\/p>\n<p>Throughout the experiment I will suggest performance tips to speed up the\u00a0<a href=\"https:\/\/web.dev\/first-contentful-paint\">first contentful paint<\/a> and perceived loading time of the page. Some of these tips may not affect the amount of data transferred <em>directly<\/em>, but do generally involve deferring the download of less important resources, which on slow connections may mean the resources are never downloaded and data is saved.<\/p>\n<h3>The Experiment<\/h3>\n<p>Without any further ado, I loaded google.com, using 402 KB of my budget and spending $0.03 (around 1% of my Zimbabwe budget).<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/71c8184e-85af-41d6-9253-1a2d74cdb5ec\/02-i-used-the-web-for-a-day-on-a-50-mb-budget.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/02-i-used-the-web-for-a-day-on-a-50-mb-budget.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/71c8184e-85af-41d6-9253-1a2d74cdb5ec\/02-i-used-the-web-for-a-day-on-a-50-mb-budget.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/71c8184e-85af-41d6-9253-1a2d74cdb5ec\/02-i-used-the-web-for-a-day-on-a-50-mb-budget.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/71c8184e-85af-41d6-9253-1a2d74cdb5ec\/02-i-used-the-web-for-a-day-on-a-50-mb-budget.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/71c8184e-85af-41d6-9253-1a2d74cdb5ec\/02-i-used-the-web-for-a-day-on-a-50-mb-budget.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/02-i-used-the-web-for-a-day-on-a-50-mb-budget.png?w=900\" sizes=\"100vw\" alt=\"402 KB transferred, 1.1 MB resources, 24 requests\"><\/a><figcaption>\n      402 KB transferred, 1.1 MB resources, 24 requests. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/71c8184e-85af-41d6-9253-1a2d74cdb5ec\/02-i-used-the-web-for-a-day-on-a-50-mb-budget.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>All in all, not a bad page size, but I wondered where those 24 network requests were coming from and whether or not the page could be made any lighter.<\/p>\n<h4>Google Homepage \u2014 DOM<\/h4>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/69e02a99-4481-46bd-b2a9-e5411991a865\/03-i-used-the-web-for-a-day-on-a-50-mb-budget.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/03-i-used-the-web-for-a-day-on-a-50-mb-budget.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/69e02a99-4481-46bd-b2a9-e5411991a865\/03-i-used-the-web-for-a-day-on-a-50-mb-budget.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/69e02a99-4481-46bd-b2a9-e5411991a865\/03-i-used-the-web-for-a-day-on-a-50-mb-budget.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/69e02a99-4481-46bd-b2a9-e5411991a865\/03-i-used-the-web-for-a-day-on-a-50-mb-budget.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/69e02a99-4481-46bd-b2a9-e5411991a865\/03-i-used-the-web-for-a-day-on-a-50-mb-budget.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/03-i-used-the-web-for-a-day-on-a-50-mb-budget.png?w=900\" sizes=\"100vw\" alt=\"\"><\/a><figcaption>\n      Chrome devtools screenshot of the DOM, where I\u2019ve expanded one inline <code>style<\/code> tag. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/69e02a99-4481-46bd-b2a9-e5411991a865\/03-i-used-the-web-for-a-day-on-a-50-mb-budget.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>Looking at the page markup, there are no\u00a0external stylesheets \u2014 all of the CSS is inline.<\/p>\n<h5>Performance Tip #1: Inline Critical CSS<\/h5>\n<p>This is good for performance as it saves the browser having to make an additional network request in order to fetch an external stylesheet, so the styles can be parsed and applied immediately for the first contentful paint. There\u2019s a trade-off to be made here, as external stylesheets can be cached but inline ones cannot (unless you\u00a0<a href=\"https:\/\/github.com\/ChrisBAshton\/inline-cacher\">get clever with JavaScript<\/a>).<\/p>\n<p>The general advice is for your <a href=\"https:\/\/web.dev\/extract-critical-css\">critical styles<\/a> (anything <a href=\"https:\/\/www.abtasty.com\/blog\/above-the-fold\/\">above-the-fold<\/a>) to be inline, and for the rest of your styling to be external and loaded asynchronously. Asynchronous loading of CSS can be achieved in <a href=\"https:\/\/www.filamentgroup.com\/lab\/load-css-simpler\/\">one remarkably clever line of HTML<\/a>:<\/p>\n<div>\n<pre><code><link rel=\"stylesheet\" href=\"\/path\/to\/my.css\" media=\"print\" onload=\"this.media='all'\"><\/code><\/pre>\n<\/div>\n<p>The devtools show a prettified version of the DOM. If you want to see what was actually downloaded to the browser, switch to the Sources tab and find the document.<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/8cf45731-08f8-4e31-b0c7-5dec6b235e41\/a-wall-of-minified-code.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/a-wall-of-minified-code.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/8cf45731-08f8-4e31-b0c7-5dec6b235e41\/a-wall-of-minified-code.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/8cf45731-08f8-4e31-b0c7-5dec6b235e41\/a-wall-of-minified-code.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/8cf45731-08f8-4e31-b0c7-5dec6b235e41\/a-wall-of-minified-code.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/8cf45731-08f8-4e31-b0c7-5dec6b235e41\/a-wall-of-minified-code.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/a-wall-of-minified-code.png?w=900\" sizes=\"100vw\" alt=\"A wall of minified code.\"><\/a><figcaption>\n      Switching to Sources and finding the index shows the \u2018raw\u2019 HTML that was delivered to the browser. What a mess! (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/8cf45731-08f8-4e31-b0c7-5dec6b235e41\/a-wall-of-minified-code.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>You can see there is a LOT of inline JavaScript here. It\u2019s worth noting that it has been uglified rather than merely minified.<\/p>\n<h5>Performance Tip #2: Minify And Uglify Your Assets<\/h5>\n<p>Minification removes unnecessary spaces and characters, but uglification actually \u2018mangles\u2019 the code to be shorter.\u00a0The tell-tale sign is that the code contains short, machine-generated variable names rather than untouched source code. This is good as it means the script is smaller and quicker to download.<\/p>\n<p>Even so, inline scripts look to be roughly 120 KB of the 210 KB page resource (about half the 60 KB gzipped size). In addition, there are five external JavaScript files amounting to 291 KB of the 402 KB downloaded:<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/dbc81fd5-f81e-4f44-8f2b-c1065ad26ed3\/five-external-javascript-files.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/five-external-javascript-files.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/dbc81fd5-f81e-4f44-8f2b-c1065ad26ed3\/five-external-javascript-files.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/dbc81fd5-f81e-4f44-8f2b-c1065ad26ed3\/five-external-javascript-files.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/dbc81fd5-f81e-4f44-8f2b-c1065ad26ed3\/five-external-javascript-files.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/dbc81fd5-f81e-4f44-8f2b-c1065ad26ed3\/five-external-javascript-files.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/five-external-javascript-files.png?w=900\" sizes=\"100vw\" alt=\"Network tab of DevTools showing the external javascript files\"><\/a><figcaption>\n      Five external JavaScript files in the Network tab of the devtools. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/dbc81fd5-f81e-4f44-8f2b-c1065ad26ed3\/five-external-javascript-files.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>This means that JavaScript accounts for about 80 percent of the overall page weight.<\/p>\n<p>This isn\u2019t useless JavaScript; Google has to have some in order to display suggestions as you type. But I suspect a lot of it is tracking code and advertising setup.<\/p>\n<p>For comparison, I disabled JavaScript and reloaded the page:<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/8fdcaa1a-0691-4ba2-a9e3-b2b236af5d88\/disabled-js-version-of-google-search.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/disabled-js-version-of-google-search.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/8fdcaa1a-0691-4ba2-a9e3-b2b236af5d88\/disabled-js-version-of-google-search.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/8fdcaa1a-0691-4ba2-a9e3-b2b236af5d88\/disabled-js-version-of-google-search.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/8fdcaa1a-0691-4ba2-a9e3-b2b236af5d88\/disabled-js-version-of-google-search.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/8fdcaa1a-0691-4ba2-a9e3-b2b236af5d88\/disabled-js-version-of-google-search.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/disabled-js-version-of-google-search.png?w=900\" sizes=\"100vw\" alt=\"DevTools showing only 5 network requests\"><\/a><figcaption>\n      The disabled JS version of Google search was only 102 KB and had just 5 network requests. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/8fdcaa1a-0691-4ba2-a9e3-b2b236af5d88\/disabled-js-version-of-google-search.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>The JS-disabled version of Google search is just 102 KB, as opposed to 402 KB. Although Google can\u2019t provide autosuggestions under these conditions, the site is still functional, and I\u2019ve just cut my data usage down to a quarter of what it was. If I really did have to limit my data usage in the long term, one of the first things I\u2019d do is disable JavaScript. <a href=\"https:\/\/www.smashingmagazine.com\/2018\/05\/using-the-web-with-javascript-turned-off\/\">It\u2019s not as bad as it sounds<\/a>.<\/p>\n<h5>Performance Tip #3: Less Is More<\/h5>\n<p>Inlining, uglifying and minifying assets is all well and good, but the best performance comes from not sending down the assets in the first place.<\/p>\n<ul>\n<li>Before adding any new features, do you have a <a href=\"https:\/\/web.dev\/performance-budgets-101\">performance budget<\/a> in place?<\/li>\n<li>Before adding JavaScript to your site, can your feature be accomplished using plain HTML? (For example, <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Learn\/HTML\/Forms\/Form_validation#Using_built-in_form_validation\">HTML5 form validation<\/a>).<\/li>\n<li>Before pulling a large JavaScript or CSS library into your application, use something like <a href=\"https:\/\/bundlephobia.com\/\">bundlephobia.com<\/a> to measure how big it is. Is the convenience worth the weight? Can you accomplish the same thing using vanilla code at a much smaller data size?<\/li>\n<\/ul>\n<h4>Analysing The Resource Info<\/h4>\n<p>There\u2019s a lot to unpack here, so let\u2019s get cracking. I\u2019ve only got 50 MB to play with, so I\u2019m going to milk every bit of this page load. Settle in for a short Chrome Devtools tutorial.<\/p>\n<p>402 KB transferred, but 1.1 MB of resources: what does that actually mean?<\/p>\n<p>It means 402 KB of content was actually downloaded, but in its compressed form (using a compression algorithm such as <a href=\"https:\/\/medium.com\/oyotech\/how-brotli-compression-gave-us-37-latency-improvement-14d41e50fee4\">gzip or brotli<\/a>). The browser then had to do some work to unpack it into something meaningful. The total size of the unpacked data is 1.1 MB.<\/p>\n<p>This unpacking isn\u2019t free \u2014 <a href=\"https:\/\/stackoverflow.com\/questions\/16803876\/browser-gzip-decompression-overhead-speed\/16816099\">there are a few milliseconds of overhead in decompressing the resources<\/a>. But\u00a0that\u2019s a negligible overhead compared to sending 1.1MB down the wire.<\/p>\n<h5>Performance Tip #4: Compress Text-based Assets<\/h5>\n<p>As a general rule, always compress your assets, using something like gzip. But don\u2019t use compression on your images and other binary files \u2014 you should optimize these in advance at source. Compression could actually end up <a href=\"https:\/\/www.itworld.com\/article\/2693941\/why-it-doesn-t-make-sense-to-gzip-all-content-from-your-web-server.html\">making them bigger<\/a>.<\/p>\n<p>And, if you can,\u00a0<a href=\"https:\/\/www.itworld.com\/article\/2693941\/why-it-doesn-t-make-sense-to-gzip-all-content-from-your-web-server.html\">avoid compressing files that are 1500 bytes or smaller<\/a>. The smallest TCP packet size is 1500 bytes, so by compressing to, say, 800 bytes, you save nothing, as it\u2019s still transmitted in the same byte packet. Again, the cost is negligible, but wastes some compression CPU time on the server and decompression CPU time on the client.<\/p>\n<p>Now back to the Network tab in Chrome: let\u2019s dig into those priorities. Notice that resources have priority \u201cHighest\u201d to \u201cLowest\u201d \u2014 these are the browser\u2019s best guess as to what are the more important resources to download. The higher the priority, the sooner the browser will try to download the asset.<\/p>\n<h5>Performance Tip #5: Give Resource Hints To The Browser<\/h5>\n<p>The browser will guess at what the highest priority assets are, but you can <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTML\/Preloading_content\">provide a resource hint<\/a> using the\u00a0<code><link rel=\"preload\"><\/code>\u00a0tag, instructing the browser to download the asset as soon as possible. It\u2019s a good idea to preload fonts, logos and anything else that appears above the fold.<\/p>\n<p>Let\u2019s talk about caching. I\u2019m going to hold ALT and right-click to change my column headers to unlock some more juicy information. We\u2019re going to check out Cache-Control.<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/cache-control.png\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/cache-control.png?resize=481%2C542\" width=\"481\" height=\"542\" alt=\"Screenshot showing how to display cache-control information\"><\/a><figcaption>There are lots of interesting fields tucked away behind ALT. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/8831ed71-56a8-4431-a39f-298dd4bc072c\/screenshot-showing-how-to-display-cache-control-information.png\">Large preview<\/a>)<\/figcaption><\/figure>\n<p>Cache-Control denotes whether or not a resource can be cached, how long it can be cached for, and what rules it should follow around <a href=\"https:\/\/traffic-control-cdn.readthedocs.io\/en\/latest\/basics\/cache_revalidation.html\">revalidating<\/a>.\u00a0Setting proper cache values is crucial to keeping the data cost of repeat visits down.<\/p>\n<div><\/div>\n<h5>Performance Tip #6: Set cache-control Headers On All Cacheable Assets<\/h5>\n<p>Note that the cache-control value begins with a directive of <code>public<\/code>\u00a0or <code>private<\/code>, followed by an expiration value (e.g. <code>max-age=31536000<\/code>). What does the directive mean, and why the oddly specific <code>max-age<\/code>\u00a0value?<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/06e8d48f-193e-4370-b41e-7d68083bd0fe\/screenshot-of-google-network-tab-with-cache-control-column-visible.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/screenshot-of-google-network-tab-with-cache-control-column-visible.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/06e8d48f-193e-4370-b41e-7d68083bd0fe\/screenshot-of-google-network-tab-with-cache-control-column-visible.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/06e8d48f-193e-4370-b41e-7d68083bd0fe\/screenshot-of-google-network-tab-with-cache-control-column-visible.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/06e8d48f-193e-4370-b41e-7d68083bd0fe\/screenshot-of-google-network-tab-with-cache-control-column-visible.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/06e8d48f-193e-4370-b41e-7d68083bd0fe\/screenshot-of-google-network-tab-with-cache-control-column-visible.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/screenshot-of-google-network-tab-with-cache-control-column-visible.png?w=900\" sizes=\"100vw\" alt=\"Screenshot of Google network tab with cache-control column visible\"><\/a><figcaption>\n      A mixture of max-age values and public\/private. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/06e8d48f-193e-4370-b41e-7d68083bd0fe\/screenshot-of-google-network-tab-with-cache-control-column-visible.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>The value <code>31536000<\/code> is the number of seconds there are in a year, and is the theoretical maximum value allowed by the cache-control specification. It is common to see this value applied to all static assets and effectively means \u201cthis resource isn\u2019t going to change\u201d.\u00a0In practice, <a href=\"https:\/\/ashton.codes\/set-cache-control-max-age-1-year\/\">no browser is going to cache for an entire year<\/a>, but it will cache the asset for as long as makes sense.<\/p>\n<p>To explain the public\/private directive, we must explain the two main caches that exist off the server. First, there is the traditional browser cache, where the resource is stored on the user\u2019s machine (the \u2018client\u2019). And then there is the CDN cache, which sits between the client and the server; resources are cached at the CDN level to prevent the CDN from requesting the resource from the origin server over and over again.<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/880e8060-6e77-4b4d-9f68-664de2152a3a\/incapsula-cdn-caching.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/incapsula-cdn-caching.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/880e8060-6e77-4b4d-9f68-664de2152a3a\/incapsula-cdn-caching.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/880e8060-6e77-4b4d-9f68-664de2152a3a\/incapsula-cdn-caching.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/880e8060-6e77-4b4d-9f68-664de2152a3a\/incapsula-cdn-caching.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/880e8060-6e77-4b4d-9f68-664de2152a3a\/incapsula-cdn-caching.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/incapsula-cdn-caching.png?w=900\" sizes=\"100vw\" alt=\"Diagram showing how caches interact with the server\"><\/a><figcaption><a href=\"https:\/\/awesome-tech.readthedocs.io\/caching\/\">Source<\/a>. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/880e8060-6e77-4b4d-9f68-664de2152a3a\/incapsula-cdn-caching.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>A <code>Cache-Control<\/code>\u00a0directive of <code>public<\/code>\u00a0allows the resource to be cached in both the client and the CDN. A value of <code>private<\/code>\u00a0means only the client can cache it; the CDN is not supposed to. This latter value is typically used for pages or assets that exist behind authentication, where it is fine to be cached on the client but we wouldn\u2019t want to leak private information by caching it in the CDN and delivering it to other users.<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/1010e6d4-6f0c-4d95-a088-67bf4e4b1b2c\/screenshot-of-google-logo-cache-control-setting.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/screenshot-of-google-logo-cache-control-setting.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/1010e6d4-6f0c-4d95-a088-67bf4e4b1b2c\/screenshot-of-google-logo-cache-control-setting.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/1010e6d4-6f0c-4d95-a088-67bf4e4b1b2c\/screenshot-of-google-logo-cache-control-setting.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/1010e6d4-6f0c-4d95-a088-67bf4e4b1b2c\/screenshot-of-google-logo-cache-control-setting.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/1010e6d4-6f0c-4d95-a088-67bf4e4b1b2c\/screenshot-of-google-logo-cache-control-setting.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/screenshot-of-google-logo-cache-control-setting.png?w=900\" sizes=\"100vw\" alt=\"Screenshot of Google logo cache-control setting: private, max-age=31536000\"><\/a><figcaption>\n      A mixture of max-age values and public\/private. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/1010e6d4-6f0c-4d95-a088-67bf4e4b1b2c\/screenshot-of-google-logo-cache-control-setting.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>One thing that got my attention was that the Google logo has a cache control of \u201cprivate\u201d. Other images on the page do have a public cache, and I don\u2019t know why the logo would be treated any differently. If you have any ideas, let me know in the comments!<\/p>\n<p>I refreshed the page and most of the resources were served from cache, apart from the page itself, which as you\u2019ve seen already is <code>private, max-age=0<\/code>, meaning it cannot be cached. This is normal for dynamic web pages where it is important that the user always gets the very latest page when they refresh.<\/p>\n<p>It was at this point I accidentally clicked on an \u2018Explanation\u2019 URL in the devtools, which took me to the <a href=\"https:\/\/developers.google.com\/web\/tools\/chrome-devtools\/network\/reference\">network analysis reference<\/a>, costing me about 5 MB of my budget. Oops.<\/p>\n<h3>Google Dev Docs<\/h3>\n<p>4.2 MB of this new 5 MB page was down to images; specifically SVGs. The weightiest of these was 186 KB, which isn\u2019t particularly big \u2014 there were just so many of them, and they all downloaded at once.<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/gif-scrolling-down-the-very-long-dev-docs-page.gif\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/gif-scrolling-down-the-very-long-dev-docs-page.gif?resize=600%2C409\" width=\"600\" height=\"409\" alt=\"Gif scrolling down the very long dev docs page\"><\/a><figcaption>This is a loooong page. All the images downloaded on page load. (<a href=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/gif-scrolling-down-the-very-long-dev-docs-page.gif\">Large preview<\/a>)<\/figcaption><\/figure>\n<p>That 5 MB page load was 10% of my budget for today. So far I\u2019ve used 5.5 MB, including the no-JavaScript reload of the Google homepage, and spent $0.40. I didn\u2019t even mean to open this page.<\/p>\n<p>What would have been a better user experience here?<\/p>\n<h5>Performance Tip #7: Lazy-load Your Images<\/h5>\n<p>Ordinarily, if I accidentally clicked on a link, I would hit the back button in my browser. I\u2019d have received no benefit whatsoever from downloading those images \u2014 what a waste of 4.2 MB!<\/p>\n<p>Apart from video, where you generally know what you\u2019re getting yourself into, images are by far the biggest culprit to data usage on the web. A <a href=\"https:\/\/blog.uploadcare.com\/image-optimization-and-performance-score-23516ebdd31d\">study of the world\u2019s top 500 websites<\/a>\u00a0found that images take up to 53% of the average page weight. \u201cThis means they have a big impact on page-loading times and subsequently overall performance\u201d.<\/p>\n<p>Instead of downloading all of the images on page load, it is good practice to lazy-load the images so that only users who are engaged with the page pay the cost of downloading them. Users who choose not to scroll below the fold therefore don\u2019t waste any unnecessary bandwidth downloading images they\u2019ll never see.<\/p>\n<p>There\u2019s a great <a href=\"https:\/\/css-tricks.com\/tips-for-rolling-your-own-lazy-loading\/\">css-tricks.com guide to rolling out lazy-loading for images<\/a>\u00a0which offers a good balance between those on good connections, those on poor connections, and those with JavaScript disabled.<\/p>\n<p>If this page had implemented lazy loading as per the guide above, each of the 38 SVGs would have been represented by a 1 KB placeholder image by default, and only loaded into view on scroll.<\/p>\n<h5>Performance Tip #8: Use The Right Format For Your Images<\/h5>\n<p>I thought that Google had missed a trick by not using <a href=\"https:\/\/developers.google.com\/speed\/webp\/\">WebP<\/a>, which is an image format that is 26% smaller in size compared to PNGs (with no loss in quality) and 25-34% smaller in size compared to JPEGs (and of a comparable quality). I thought I\u2019d have a go at converting SVG to WebP.<\/p>\n<p>Converting to WebP did bring one of the SVGs down from 186 KB to just 65 KB, but actually, looking at the images side by side, the WebP came out grainy:<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/64eeb0ac-96ac-44ca-8164-59749f3b850f\/the-svg-left-is-noticeably-crisper-than-the-webp.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/the-svg-left-is-noticeably-crisper-than-the-webp.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/64eeb0ac-96ac-44ca-8164-59749f3b850f\/the-svg-left-is-noticeably-crisper-than-the-webp.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/64eeb0ac-96ac-44ca-8164-59749f3b850f\/the-svg-left-is-noticeably-crisper-than-the-webp.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/64eeb0ac-96ac-44ca-8164-59749f3b850f\/the-svg-left-is-noticeably-crisper-than-the-webp.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/64eeb0ac-96ac-44ca-8164-59749f3b850f\/the-svg-left-is-noticeably-crisper-than-the-webp.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/the-svg-left-is-noticeably-crisper-than-the-webp.png?w=900\" sizes=\"100vw\" alt=\"Comparison of the two images\"><\/a><figcaption>\n      The SVG (left) is noticeably crisper than the WebP (right). (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/64eeb0ac-96ac-44ca-8164-59749f3b850f\/the-svg-left-is-noticeably-crisper-than-the-webp.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>I then tried converting one of the PNGs to WebP, which is supposed to be lossless and should come out smaller. However, the WebP output was\u00a0*heavier*\u00a0(127 KB, from 109 KB)!<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/09abae72-2997-4230-a99e-52eb120006c5\/the-png-left-is-a-similar-quality-to-the-webp.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/the-png-left-is-a-similar-quality-to-the-webp.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/09abae72-2997-4230-a99e-52eb120006c5\/the-png-left-is-a-similar-quality-to-the-webp.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/09abae72-2997-4230-a99e-52eb120006c5\/the-png-left-is-a-similar-quality-to-the-webp.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/09abae72-2997-4230-a99e-52eb120006c5\/the-png-left-is-a-similar-quality-to-the-webp.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/09abae72-2997-4230-a99e-52eb120006c5\/the-png-left-is-a-similar-quality-to-the-webp.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/the-png-left-is-a-similar-quality-to-the-webp.png?w=900\" sizes=\"100vw\" alt=\"Comparison of the two images\"><\/a><figcaption>\n      The PNG (left) is a similar quality to the WebP (right) but is smaller at 109 KB compared to 127 KB. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/09abae72-2997-4230-a99e-52eb120006c5\/the-png-left-is-a-similar-quality-to-the-webp.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>This surprised me. WebP isn\u2019t necessarily the silver bullet we think it is, and even Google have neglected to use it on this page.<\/p>\n<p>So my advice would be: where possible, experiment with different image formats on a per-image basis. The format that keeps the best quality for the smallest size may not be the one you expect.<\/p>\n<p>Now back to the DOM. I came across this:<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/3202ff09-d70a-4462-bd2a-af498fbf9ff7\/04-i-used-the-web-for-a-day-on-a-50-mb-budget.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/04-i-used-the-web-for-a-day-on-a-50-mb-budget.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/3202ff09-d70a-4462-bd2a-af498fbf9ff7\/04-i-used-the-web-for-a-day-on-a-50-mb-budget.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/3202ff09-d70a-4462-bd2a-af498fbf9ff7\/04-i-used-the-web-for-a-day-on-a-50-mb-budget.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/3202ff09-d70a-4462-bd2a-af498fbf9ff7\/04-i-used-the-web-for-a-day-on-a-50-mb-budget.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/3202ff09-d70a-4462-bd2a-af498fbf9ff7\/04-i-used-the-web-for-a-day-on-a-50-mb-budget.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/04-i-used-the-web-for-a-day-on-a-50-mb-budget.png?w=900\" sizes=\"100vw\" alt=\"Screenshot of code\"><\/a><figcaption>\n      (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/3202ff09-d70a-4462-bd2a-af498fbf9ff7\/04-i-used-the-web-for-a-day-on-a-50-mb-budget.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>Notice the <code>async<\/code> keyword on the Google analytics script?<\/p>\n<figure><a href=\"https:\/\/i0.wp.com\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/0b2a8a71-6573-4a7b-8008-d73a1c54f318\/screenshot-of-performance-analysis-output-of-devtools.png?ssl=1\"><\/p>\n<p>    <img data-recalc-dims=\"1\" decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/screenshot-of-performance-analysis-output-of-devtools.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/0b2a8a71-6573-4a7b-8008-d73a1c54f318\/screenshot-of-performance-analysis-output-of-devtools.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/0b2a8a71-6573-4a7b-8008-d73a1c54f318\/screenshot-of-performance-analysis-output-of-devtools.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/0b2a8a71-6573-4a7b-8008-d73a1c54f318\/screenshot-of-performance-analysis-output-of-devtools.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/0b2a8a71-6573-4a7b-8008-d73a1c54f318\/screenshot-of-performance-analysis-output-of-devtools.png 2000w\" src=\"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/screenshot-of-performance-analysis-output-of-devtools.png?w=900\" sizes=\"100vw\" alt=\"Screenshot of performance analysis output of devtools\"><\/a><figcaption>\n      Google analytics has \u2018low\u2019 priority. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/0b2a8a71-6573-4a7b-8008-d73a1c54f318\/screenshot-of-performance-analysis-output-of-devtools.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>Despite being one of the first things in the head of the document, this was given a low priority, as we\u2019ve explicitly opted out of being a blocking request by using the <code>async<\/code>\u00a0keyword.<\/p>\n<p>A blocking request is one that stops the rendering of the page. A <code><script><\/code>\u00a0call is blocking by default, stopping the parsing of the HTML until the script has downloaded, compiled and executed. This is why we traditionally put <code><script><\/code>\u00a0calls at the end of the document.<\/p>\n<h5>Performance Tip #9: Avoid Writing Blocking Script Calls<\/h5>\n<p>By adding the\u00a0<code>async<\/code>\u00a0attribute to our\u00a0<code><script><\/code>\u00a0tag, we\u2019re telling the browser not to stop rendering the page but to download the script in the background. If the HTML is still being parsed by the time the script is downloaded, the parsing is paused while the script is executed, and then resumed. This is significantly better than blocking the rendering as soon as <code><script><\/code>\u00a0is encountered.<\/p>\n<p>There is also a <code>defer<\/code>\u00a0attribute, which is subtly different. <code><script defer><\/code>\u00a0tells the browser to render the page while the script loads in the background, and even if the HTML is still being parsed by the time the script is downloaded, the script must wait until the page is rendered before it can be executed. This makes the script completely non-blocking. Read \u201c<a href=\"https:\/\/flaviocopes.com\/javascript-async-defer\/\">Efficiently load JavaScript with defer and async<\/a>\u201d for more information.<\/p>\n<p>Anyway, enough Google dissecting. It\u2019s time to try out another site. I\u2019ve still got almost 45 MB of my budget left!<\/p>\n<h2>Amazon<\/h2>\n<figure><a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/3881c367-7ef6-4099-9d62-a856e02e4530\/screenshot-of-amazon-homepage.png\"><\/p>\n<p>    <img decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/screenshot-of-amazon-homepage.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/3881c367-7ef6-4099-9d62-a856e02e4530\/screenshot-of-amazon-homepage.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/3881c367-7ef6-4099-9d62-a856e02e4530\/screenshot-of-amazon-homepage.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/3881c367-7ef6-4099-9d62-a856e02e4530\/screenshot-of-amazon-homepage.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/3881c367-7ef6-4099-9d62-a856e02e4530\/screenshot-of-amazon-homepage.png 2000w\" src=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/screenshot-of-amazon-homepage.png\" sizes=\"100vw\" alt=\"screenshot of Amazon homepage\"><\/a><figcaption>\n      (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/3881c367-7ef6-4099-9d62-a856e02e4530\/screenshot-of-amazon-homepage.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>The Amazon homepage loaded with a total weight of about 6 MB. One of these was a 587 KB image that I couldn\u2019t even find on the page. This was a PNG, presumably to have crisp text, but on a photographic background \u2014 a classic combination that\u2019s terrible for performance.<\/p>\n<figure><a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/fe47c512-b890-4e8a-bebd-0e0529cc565b\/image-of-spanners-with-overlaid-text.png\"><\/p>\n<p>    <img decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/image-of-spanners-with-overlaid-text.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/fe47c512-b890-4e8a-bebd-0e0529cc565b\/image-of-spanners-with-overlaid-text.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/fe47c512-b890-4e8a-bebd-0e0529cc565b\/image-of-spanners-with-overlaid-text.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/fe47c512-b890-4e8a-bebd-0e0529cc565b\/image-of-spanners-with-overlaid-text.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/fe47c512-b890-4e8a-bebd-0e0529cc565b\/image-of-spanners-with-overlaid-text.png 2000w\" src=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/image-of-spanners-with-overlaid-text.png\" sizes=\"70vw\" alt=\"image of spanners with overlaid text: Hands-on time. Discover our tool selection for your car\"><\/a><figcaption>\n      This grainy image used over 1% of my budget. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/fe47c512-b890-4e8a-bebd-0e0529cc565b\/image-of-spanners-with-overlaid-text.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>In fact, there were a few several-hundred-kilobyte images in my network tab that I couldn\u2019t actually see on the page. I suspect a misconfiguration somewhere on Amazon, but these invisible images combined chewed through at least 1 MB of my data.<\/p>\n<p>How about the hero image? It\u2019s the main image on the page, and it\u2019s only 94 KB transferred \u2014 but it could be reduced in size by about 15% if it were cropped directly around the text and footballers. We could then apply the same background color in CSS as is in the image. This has the additional advantage of being resizable down to smaller screens whilst retaining legibility of text.<\/p>\n<figure><a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/66f2544a-b5d0-41c6-99b6-fc4c7aced358\/amazon-hero.jpg\"><\/p>\n<p>    <img decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/amazon-hero.jpg 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/66f2544a-b5d0-41c6-99b6-fc4c7aced358\/amazon-hero.jpg 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/66f2544a-b5d0-41c6-99b6-fc4c7aced358\/amazon-hero.jpg 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/66f2544a-b5d0-41c6-99b6-fc4c7aced358\/amazon-hero.jpg 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/66f2544a-b5d0-41c6-99b6-fc4c7aced358\/amazon-hero.jpg 2000w\" src=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/amazon-hero.jpg\" sizes=\"100vw\" alt=\"Screenshot says: Premier league football - Live on Prime video\"><\/a><figcaption>\n      (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/66f2544a-b5d0-41c6-99b6-fc4c7aced358\/amazon-hero.jpg\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>I\u2019ve said it once, and I\u2019ll say it again: <strong>optimising and lazy-loading your images is the single biggest benefit you can make to the page weight of your site<\/strong>.<\/p>\n<blockquote><p>Optimizing images provided, by far, the most significant data reduction. You can make the case JavaScript is a bigger deal for overall performance, but not data reduction. Optimizing or removing images is the safest way of ensuring a much lighter experience and that\u2019s the primary optimization Data Saver relies on.<br \/>\u2014 Tim Kadlec, <em><a href=\"https:\/\/timkadlec.com\/remembers\/2019-03-14-making-sense-of-chrome-lite-pages\/\">Making Sense of Chrome Lite Pages<\/a><\/em><\/p><\/blockquote>\n<p>To be fair to Amazon, if I resize the browser to a mobile size and refresh the page, the site is optimized for mobile and the total page weight is only 2.1 MB.<\/p>\n<figure><a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/e1a3d256-e421-4668-8fc4-ad3c4e2e0de1\/05-i-used-the-web-for-a-day-on-a-50-mb-budget.png\"><\/p>\n<p>    <img decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/05-i-used-the-web-for-a-day-on-a-50-mb-budget.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/e1a3d256-e421-4668-8fc4-ad3c4e2e0de1\/05-i-used-the-web-for-a-day-on-a-50-mb-budget.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/e1a3d256-e421-4668-8fc4-ad3c4e2e0de1\/05-i-used-the-web-for-a-day-on-a-50-mb-budget.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/e1a3d256-e421-4668-8fc4-ad3c4e2e0de1\/05-i-used-the-web-for-a-day-on-a-50-mb-budget.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/e1a3d256-e421-4668-8fc4-ad3c4e2e0de1\/05-i-used-the-web-for-a-day-on-a-50-mb-budget.png 2000w\" src=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/05-i-used-the-web-for-a-day-on-a-50-mb-budget.png\" sizes=\"100vw\" alt=\"101 requests, 2.1 MB transferred\"><\/a><figcaption>\n      101 requests, 2.1 MB transferred. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/e1a3d256-e421-4668-8fc4-ad3c4e2e0de1\/05-i-used-the-web-for-a-day-on-a-50-mb-budget.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>But this brings me onto my next point\u2026<\/p>\n<h5>Performance Tip #10: Don\u2019t Make Assumptions About Data Connections<\/h5>\n<p>It\u2019s difficult to detect if someone on a desktop is on a broadband connection or is tethering through a data-limited dongle or mobile. Many people work on the train like that, or live in an area where broadband infrastructure is poor but mobile signal is strong. In Amazon\u2019s case, there is room to make some big data savings on the desktop site and we shouldn\u2019t get complacent just because the screen size suggests I\u2019m not on a mobile device.<\/p>\n<p>Yes, we should expect a larger page load if our viewport is \u2018desktop sized\u2019 as the images will be larger and better optimized for the screen than a grainier mobile one. But the page shouldn\u2019t be orders of magnitude bigger.<\/p>\n<p>Moreover, I was sending the <code>Save-Data<\/code>\u00a0header with my request. This header <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Headers\/Save-Data\">explicitly indicates a preference for reduced data usage<\/a>, and I hope more websites start to take notice of it in the future.<\/p>\n<p>The initial \u2018desktop\u2019 load may have been 6 MB, but after sitting and watching it for a minute it had climbed to 8.6 MB as the lower-priority resources and event tracking kicked into action. This page weight includes almost 1.7 MB of minified JavaScript. I don\u2019t even want to <em>begin<\/em> to look at that.<\/p>\n<h5>Performance Tip #11: Use Web Workers For Your JavaScript<\/h5>\n<p>Which would be worse \u2014 1.7 MB of JavaScript or 1.7 MB of images? The answer is JavaScript: the two assets are not equivalent when it comes to performance.<\/p>\n<blockquote>\n<p>A JPEG image needs to be decoded, rasterized, and painted on the screen. A JavaScript bundle needs to be downloaded and then parsed, compiled, executed \u2014and there are a number of other steps that an engine needs to complete. Be aware that these costs are not quite equivalent.<br \/>\u2014 Addy Osmani, <em>The Cost of JavaScript in 2018<\/em><\/p>\n<\/blockquote>\n<p>If you must ship this much JavaScript, try <a href=\"https:\/\/dassur.ma\/things\/when-workers\/\">putting it in a web worker<\/a>. This keeps the bulk of JavaScript off the main thread, which is now freed up for repainting the UI, helping your web page to stay responsive on low-powered devices.<\/p>\n<p>I\u2019m now about 15.5 MB into my budget, and have spent $1.14 of my Zimbabwe data budget. I\u2019d have had to have worked for half a day as a teacher to earn the money to get this far.<\/p>\n<h3>Pinterest<\/h3>\n<p>I\u2019ve heard good things about Pinterest\u2019s performance, so I decided to put it to the test.<\/p>\n<figure><a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/e32acbef-01c4-4cbe-b5c1-6e840519f1c9\/06-i-used-the-web-for-a-day-on-a-50-mb-budget.png\"><\/p>\n<p>    <img decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/06-i-used-the-web-for-a-day-on-a-50-mb-budget.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/e32acbef-01c4-4cbe-b5c1-6e840519f1c9\/06-i-used-the-web-for-a-day-on-a-50-mb-budget.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/e32acbef-01c4-4cbe-b5c1-6e840519f1c9\/06-i-used-the-web-for-a-day-on-a-50-mb-budget.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/e32acbef-01c4-4cbe-b5c1-6e840519f1c9\/06-i-used-the-web-for-a-day-on-a-50-mb-budget.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/e32acbef-01c4-4cbe-b5c1-6e840519f1c9\/06-i-used-the-web-for-a-day-on-a-50-mb-budget.png 2000w\" src=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/06-i-used-the-web-for-a-day-on-a-50-mb-budget.png\" sizes=\"100vw\" alt=\"A staggering 327 requests, making 6.1 MB of data.\"><\/a><figcaption>\n      A staggering 327 requests, making 6.1 MB of data. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/e32acbef-01c4-4cbe-b5c1-6e840519f1c9\/06-i-used-the-web-for-a-day-on-a-50-mb-budget.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>Perhaps this isn\u2019t the fairest of tests; I was taken to the sign-in page, upon which an asynchronous process found I was logged into Facebook and logged me in automatically. The page loaded relatively quickly, but the requests crept up as more and more content was preloaded.<\/p>\n<div><\/div>\n<p>However, I saw that on subsequent page loads, the service worker surfaced much of the content \u2014 saving about half of the page weight:<\/p>\n<figure><a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/88853603-7b89-4ae1-8969-db19fac4a95d\/07-i-used-the-web-for-a-day-on-a-50-mb-budget.png\"><\/p>\n<p>    <img decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/07-i-used-the-web-for-a-day-on-a-50-mb-budget.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/88853603-7b89-4ae1-8969-db19fac4a95d\/07-i-used-the-web-for-a-day-on-a-50-mb-budget.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/88853603-7b89-4ae1-8969-db19fac4a95d\/07-i-used-the-web-for-a-day-on-a-50-mb-budget.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/88853603-7b89-4ae1-8969-db19fac4a95d\/07-i-used-the-web-for-a-day-on-a-50-mb-budget.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/88853603-7b89-4ae1-8969-db19fac4a95d\/07-i-used-the-web-for-a-day-on-a-50-mb-budget.png 2000w\" src=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/07-i-used-the-web-for-a-day-on-a-50-mb-budget.png\" sizes=\"100vw\" alt=\"8.2 \/ 15.6 MB resources, and 39 \/ 180 requests handled by the service worker cache.\"><\/a><figcaption>\n      8.2 \/ 15.6 MB resources, and 39 \/ 180 requests handled by the service worker cache. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/88853603-7b89-4ae1-8969-db19fac4a95d\/07-i-used-the-web-for-a-day-on-a-50-mb-budget.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>The Pinterest site is a progressive web app; it installed a service worker to manually handle caching of CSS and JS. I could now turn off my WiFi and continue to use the site (albeit not very usefully):<\/p>\n<figure><a href=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/loading-spinner-and-message-saying-you-re-not-connected-to-the-internet.png\"><img decoding=\"async\" src=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/loading-spinner-and-message-saying-you-re-not-connected-to-the-internet.png\" alt=\"Loading spinner and message saying: you're not connected to the internet\"><\/a><figcaption>You can\u2019t do much when you\u2019re offline. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/188acdb0-1ec0-4404-bcdb-b6cb653c5dcc\/loading-spinner-and-message-saying-you-re-not-connected-to-the-internet.png\">Large preview<\/a>)<\/figcaption><\/figure>\n<h5>Performance Tip #12: Use Service Workers To Provide Offline Support<\/h5>\n<p>Wouldn\u2019t it be great if I only had to load a website once over network, and now get all the information I need even if I\u2019m offline?<\/p>\n<p>A great example would be a website that shows the weather forecast for the week. I should only need to download that page once. If I turn off my mobile data and subsequently go back to the page at some point, it should be able to serve the last known content to me.\u00a0If I connect to the internet again and load the page, I would get a more up to date forecast, but static assets such as CSS and images should still be served locally from the service worker.<\/p>\n<p>This is possible by setting up a <a href=\"https:\/\/serviceworke.rs\/caching-strategies.html\">service worker with a good caching strategy<\/a>\u00a0so that cached pages can be re-accessed offline. The <a href=\"https:\/\/lodash.com\/docs\/\">lodash documentation website<\/a> is a nice example of a service worker in the wild:<\/p>\n<figure><a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/3ae779a9-740f-4715-9e48-fd67a9a3a8ea\/screenshot-of-devtools-showing-serviceworker-next-to-each-request.png\"><\/p>\n<p>    <img decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/screenshot-of-devtools-showing-serviceworker-next-to-each-request.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/3ae779a9-740f-4715-9e48-fd67a9a3a8ea\/screenshot-of-devtools-showing-serviceworker-next-to-each-request.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/3ae779a9-740f-4715-9e48-fd67a9a3a8ea\/screenshot-of-devtools-showing-serviceworker-next-to-each-request.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/3ae779a9-740f-4715-9e48-fd67a9a3a8ea\/screenshot-of-devtools-showing-serviceworker-next-to-each-request.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/3ae779a9-740f-4715-9e48-fd67a9a3a8ea\/screenshot-of-devtools-showing-serviceworker-next-to-each-request.png 2000w\" src=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/screenshot-of-devtools-showing-serviceworker-next-to-each-request.png\" sizes=\"100vw\" alt=\"Screenshot of devtools showing 'ServiceWorker' next to each request\"><\/a><figcaption>\n      The Lodash docs work offline. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/3ae779a9-740f-4715-9e48-fd67a9a3a8ea\/screenshot-of-devtools-showing-serviceworker-next-to-each-request.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>Content that rarely updates and is likely to be used quite regularly is a\u00a0<em>perfect<\/em> candidate for service worker treatment. Dynamic sites with ever-changing news feeds aren\u2019t quite so well suited for offline experiences, but can still benefit.<\/p>\n<figure><a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/bef23c7c-9ad0-4ac9-b646-4352bf3b34d6\/screenshot-of-chris-ashton-profile-on-pinterest.png\"><\/p>\n<p>    <img decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/screenshot-of-chris-ashton-profile-on-pinterest.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/bef23c7c-9ad0-4ac9-b646-4352bf3b34d6\/screenshot-of-chris-ashton-profile-on-pinterest.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/bef23c7c-9ad0-4ac9-b646-4352bf3b34d6\/screenshot-of-chris-ashton-profile-on-pinterest.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/bef23c7c-9ad0-4ac9-b646-4352bf3b34d6\/screenshot-of-chris-ashton-profile-on-pinterest.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/bef23c7c-9ad0-4ac9-b646-4352bf3b34d6\/screenshot-of-chris-ashton-profile-on-pinterest.png 2000w\" src=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/screenshot-of-chris-ashton-profile-on-pinterest.png\" sizes=\"100vw\" alt=\"Screenshot of Chris Ashton profile on Pinterest\"><\/a><figcaption>\n      The second Pinterest page load was 443 KB. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/bef23c7c-9ad0-4ac9-b646-4352bf3b34d6\/screenshot-of-chris-ashton-profile-on-pinterest.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>Service workers can truly save the day when you\u2019re on a tight data budget. I\u2019m not convinced the Pinterest experience was the most optimal in terms of data usage \u2013 subsequent pages were around the 0.5 MB mark even on pages with few images \u2014 but letting your JavaScript handle page requests for you and keeping the same navigational elements in place can be very performant. The BBC manages a <a href=\"https:\/\/www.bbc.co.uk\/news\/articles\/c5ll353v7y9o\">transfer size of just 3.1 KB<\/a> for return-visits to articles that are renderable via the single page application.<\/p>\n<p>So far, Pinterest alone has chewed through 14 MB, which means I\u2019ve blown around 30 MB of my budget, or $2.20 (almost a day\u2019s wages) of my Zimbabwe budget.<\/p>\n<p>I\u2019d better be careful with my final 20 MB\u2026 but where\u2019s the fun in that?<\/p>\n<h3>Gamespot<\/h3>\n<p>I picked this one because it felt noticeably sluggish on my mobile in the past and I wanted to dig into the reasons why. Sure enough, loading the homepage consumes 8.5 MB of data.<\/p>\n<figure><a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/8df6aa4b-4199-4fd0-b0fe-15f7c993796a\/screenshot-of-devtools-alongside-homepage.png\"><\/p>\n<p>    <img decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/screenshot-of-devtools-alongside-homepage.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/8df6aa4b-4199-4fd0-b0fe-15f7c993796a\/screenshot-of-devtools-alongside-homepage.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/8df6aa4b-4199-4fd0-b0fe-15f7c993796a\/screenshot-of-devtools-alongside-homepage.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/8df6aa4b-4199-4fd0-b0fe-15f7c993796a\/screenshot-of-devtools-alongside-homepage.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/8df6aa4b-4199-4fd0-b0fe-15f7c993796a\/screenshot-of-devtools-alongside-homepage.png 2000w\" src=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/screenshot-of-devtools-alongside-homepage.png\" sizes=\"100vw\" alt=\"Screenshot of devtools alongside homepage\"><\/a><figcaption>\n      The Gamespot homepage trickled up to 8.5 MB, and a whopping 347 requests. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/8df6aa4b-4199-4fd0-b0fe-15f7c993796a\/screenshot-of-devtools-alongside-homepage.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>6.5 MB of this was down to an autoplaying video halfway down the page, which \u2014 to be fair \u2014 didn\u2019t appear to download until I began scrolling. Nevertheless\u2026<\/p>\n<figure><a href=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/the-video-is-clipped-off-screen.gif\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/the-video-is-clipped-off-screen.gif\" width=\"600\" height=\"341\" alt=\"Gif screenshot of the video within my viewport\"><\/a><figcaption>The video is clipped off-screen. (<a href=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/the-video-is-clipped-off-screen.gif\">Large preview<\/a>)<\/figcaption><\/figure>\n<p>I could only see half the video in my viewport \u2014 the right hand side was clipped. It was also 30 seconds long, and I would wager that most people won\u2019t sit and watch the whole thing. This single asset more than tripled the size of the page.<\/p>\n<h5>Performance Tip #13: Don\u2019t Preload Video<\/h5>\n<p>As a rule, unless your site\u2019s primary mode of communication is video, don\u2019t preload it.<\/p>\n<p>If you\u2019re YouTube or Netflix, it\u2019s reasonable to assume that someone coming to your page will want the video to auto-load and auto-play. There is an expectation that the video will chew through some data, but that it\u2019s a fair exchange for the content. But if you\u2019re a site whose primary medium is text and image \u2014 and you just happen to offer additional video content \u2014 then don\u2019t preload the video.<\/p>\n<p>Think of news articles with embedded videos. Many users only want to skim the article headline before moving on to their next thing. Others will read the article but ignore any embeds. And others will diligently click and watch each embedded video. We shouldn\u2019t hog the bandwidth of every user on the <em>assumption<\/em> that they\u2019re going to want to watch these videos.<\/p>\n<p>To reiterate:\u00a0<a href=\"https:\/\/www.nytimes.com\/2018\/08\/01\/technology\/personaltech\/autoplay-video-fight-them.html\">users don\u2019t like autoplaying video<\/a>. As developers we only do it because our managers tell us to, and they only tell us to do it because all the coolest apps are doing it, and the coolest apps are only doing it because video ads generate 20 to 50 times more revenue than traditional ads. Google Chrome has started <a href=\"https:\/\/www.theverge.com\/2018\/5\/3\/17251104\/google-chrome-66-autoplay-sound-videos-mute\">blocking autoplay videos for some sites<\/a>, based on personal preferences, so even if you develop your site to autoplay video, there\u2019s no guarantee that\u2019s the experience your users are getting.<\/p>\n<p>If we agree that it\u2019s a good idea to make video an opt-in experience (click to play), we can take it a step further and make it click to load too. That means mocking a video placeholder image with a play button over it, and only downloading the video when you click the play button. People on fast connections should notice no difference in buffer speed, and people on slow connections will appreciate how fast the rest of your site loaded because it didn\u2019t have to preload a large video file.<\/p>\n<p>Anyway, back to Gamespot, where I was indeed forced to preload a large video file I ended up not watching. I then clicked through to a <a href=\"https:\/\/www.gamespot.com\/reviews\/final-fantasy-xiv-shadowbringers-review-dancer-in-\/1900-6417212\/\">game review page<\/a> that weighed another 8.5 MB, this time with 5.4 MB of video, before I even started scrolling down the page.<\/p>\n<p>What was\u00a0<em>really galling<\/em> was when I looked at what the video actually was. It was an <a href=\"https:\/\/static.sharethrough.com\/sfp\/hosted_video\/DS843eHqTGfEfxMBvLMh1n6uyq\/video.mp4\">advert for a Samsung TV<\/a>! This advert cost me $0.40 of my Zimbabwe wages. Not only was it pre-loaded, but it also didn\u2019t end up playing anywhere as far as I\u2019m aware, so I never actually saw it.<\/p>\n<figure><a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/1d1b0ac0-1909-4542-b5e4-2096419ba635\/screenshot-of-the-offending-request.png\"><\/p>\n<p>    <img decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/screenshot-of-the-offending-request.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/1d1b0ac0-1909-4542-b5e4-2096419ba635\/screenshot-of-the-offending-request.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/1d1b0ac0-1909-4542-b5e4-2096419ba635\/screenshot-of-the-offending-request.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/1d1b0ac0-1909-4542-b5e4-2096419ba635\/screenshot-of-the-offending-request.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/1d1b0ac0-1909-4542-b5e4-2096419ba635\/screenshot-of-the-offending-request.png 2000w\" src=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/screenshot-of-the-offending-request.png\" sizes=\"100vw\" alt=\"Screenshot of the offending request\"><\/a><figcaption>\n      This advert wasted 5.4 MB of my precious data. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/1d1b0ac0-1909-4542-b5e4-2096419ba635\/screenshot-of-the-offending-request.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>The \u2018real\u2019 video \u2014 the gameplay footage (in other words, the content) \u2014 wasn\u2019t actually loaded until I clicked on it. And that ploughed through my remaining data in seconds.<\/p>\n<p>That\u2019s it. That\u2019s my 50 MB gone. I\u2019ll need to work another 1.5 days as a Zimbabwean schoolteacher to repeat the experience.<\/p>\n<h5>Performance Tip #14: Optimize For First Page Load<\/h5>\n<p>What\u2019s striking is that I used 50 MB of data and in most cases, I only visited one or two pages on any given site. If you think about it, this is true of most user journeys today.<\/p>\n<p>Think about the last time you Googled something. You no doubt clicked on the first search result. If you got your answer, you closed the tab, or else you hit the back button and moved onto the next search result.<\/p>\n<p>With the exception of a few so-called \u2018destination sites\u2019 such as Facebook or YouTube, where users habitually go as a starting point for other activities, the majority of user journeys are ephemeral. We stumble across random sites to get the answers to our questions, never to return to those sites again.<\/p>\n<p>Web development practices are heavily skewed towards optimising for repeat visitors. \u201cCache these assets \u2014 they\u2019ll come in handy later\u201d. \u201cPre-load this onward journey, in case the user clicks to read more\u201d. \u201cSubscribe to our mailing list\u201d.<\/p>\n<p>Instead, I believe we should optimize heavily for one-off visitors. Call it a controversial opinion, but maybe caching isn\u2019t really all that important. How important can a cached resource that never gets surfaced again <em>be<\/em>? And perhaps users aren\u2019t actually going to subscribe to your mailing list after reading just the one article, so downloading the JavaScript and CSS for the mail subscription modal is both a waste of data and an <a href=\"https:\/\/www.smashingmagazine.com\/2019\/06\/web-designers-speed-mobile-websites\/#2-stop-using-cumbersome-design-elements\">annoying user experience<\/a>.<\/p>\n<h3>The Decline Of Proxy Browsers<\/h3>\n<p>I had hoped to try out Opera Mini as part of this experiment. Opera Mini is a mobile web browser which proxies web pages through Opera\u2019s compression servers. It accounts for 1.42% of global traffic as of June 2019, according to caniuse.com.<\/p>\n<p>Opera Mini claims to save up to 90% of data by doing some pretty intensive transcoding. HTML is parsed, images are compressed, styling is applied, and a certain amount of JavaScript is executed on Opera\u2019s servers. The server doesn\u2019t respond with HTML as you might expect \u2014 it actually transcodes the data into Opera Binary Markup Language (OBML), which is progressively loaded by Opera Mini on the device. It renders what is essentially an interactive \u2018snapshot\u2019 of the web page \u2014 think of it as a PDF with hyperlinks inside it. Read Tiffany Brown\u2019s excellent article, \u201c<a href=\"https:\/\/dev.opera.com\/articles\/opera-mini-and-javascript\/\">Opera Mini and JavaScript<\/a>\u201d for a technical deep-dive.<\/p>\n<p>It would have been a perfect way to eek my 50 MB budget as far as possible. Unfortunately, Opera Mini is no longer available on iOS in the UK. Attempting to visit it in the <a href=\"https:\/\/apps.apple.com\/app\/id363729560\">app store<\/a> throws an error:<\/p>\n<figure><a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/c333e799-9c35-4559-b1e1-8537c6eac434\/opera-mini-in-app-store.png\"><\/p>\n<p>    <img decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/opera-mini-in-app-store.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/c333e799-9c35-4559-b1e1-8537c6eac434\/opera-mini-in-app-store.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/c333e799-9c35-4559-b1e1-8537c6eac434\/opera-mini-in-app-store.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/c333e799-9c35-4559-b1e1-8537c6eac434\/opera-mini-in-app-store.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/c333e799-9c35-4559-b1e1-8537c6eac434\/opera-mini-in-app-store.png 2000w\" src=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/opera-mini-in-app-store.png\" sizes=\"100vw\" alt=\"The item you've requested is not currently available in the UK Store.\"><\/a><figcaption>\n      (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/c333e799-9c35-4559-b1e1-8537c6eac434\/opera-mini-in-app-store.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>It\u2019s still available \u201c<a href=\"https:\/\/twitter.com\/opera\/status\/1084736938312110080\">in some markets<\/a>\u201d but reading between the lines, Opera will be phasing out Opera Mini for its new app \u2014 Opera Touch \u2014 which <a href=\"https:\/\/www.guidingtech.com\/opera-mini-vs-opera-touch-comparison-differences\/\">doesn\u2019t have any data-saving functionality<\/a>\u00a0apart from the ability to natively block ads.<\/p>\n<p>Opera desktop used to have a \u2018Turbo mode\u2019, acting as a traditional proxy server (returning a HTML document instead of OBML), applying data-saving techniques but less intensively than Opera Mini. According to Opera, JavaScript continues to work and \u201cyou get all the videos, photos and text that you normally would, but you eat up less data and load pages faster\u201d. However,\u00a0<a href=\"https:\/\/techdows.com\/2019\/06\/opera-quietly-removed-turbo-mode-from-their-browser.html\">Opera quietly removed Turbo mode in v60<\/a>\u00a0earlier this year, and Opera Touch\u00a0<a href=\"https:\/\/forums.opera.com\/topic\/26886\/no-turbo-mode-for-opera-touch\">doesn\u2019t have a Turbo mode<\/a>\u00a0either. Turbo mode is currently only available on Opera for Android.<\/p>\n<p>Android is where all the action is in terms of data-saving technology.\u00a0Chrome offers a \u2018Lite mode\u2019 on its mobile browser for Android, which is not available for iPhones or iPads because of \u201c<a href=\"https:\/\/support.google.com\/chrome\/answer\/2392284\">platform constraints<\/a>\u201c. Outside of mobile, Google used to provide a \u2018Data Saver\u2019 extension for Chrome desktop, but <a href=\"https:\/\/venturebeat.com\/2019\/04\/23\/google-kills-chrome-data-saver-extension\/\">this was canned in April<\/a>.<\/p>\n<p>Lite mode for Chrome Android can be forcibly enabled, or automatically kicks in when the network\u2019s effective connection type is 2G or worse, or when Chrome estimates the page will take more than 5 seconds to reach first contentful paint. Under these conditions, <a href=\"https:\/\/www.zdnet.com\/article\/google-announces-chrome-lite-pages-a-way-to-speed-up-https-sites-on-slow-connections\/\">Chrome will request the lite version of the HTTPS URL as cached by Google\u2019s servers<\/a>, and display this stripped-down version inside the user\u2019s browser, alongside a \u201cLite\u201d marker in the address bar.<\/p>\n<figure><a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/69282232-f726-4760-9743-73373c5ee43f\/chrome-lite-pages.png\"><\/p>\n<p>    <img decoding=\"async\" srcset=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/chrome-lite-pages.png 400w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_800\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/69282232-f726-4760-9743-73373c5ee43f\/chrome-lite-pages.png 800w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1200\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/69282232-f726-4760-9743-73373c5ee43f\/chrome-lite-pages.png 1200w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_1600\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/69282232-f726-4760-9743-73373c5ee43f\/chrome-lite-pages.png 1600w,\n\t\t\t        https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_auto\/w_2000\/https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/69282232-f726-4760-9743-73373c5ee43f\/chrome-lite-pages.png 2000w\" src=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/chrome-lite-pages.png\" sizes=\"100vw\" alt=\"Screenshot showing button in toolbar denoting 'Lite' mode\"><\/a><figcaption>\n      \u2018Lite mode\u2019 on Chrome for Android. Image: Google. (<a href=\"https:\/\/cloud.netlifyusercontent.com\/assets\/344dbf88-fdf9-42bb-adb4-46f01eedd629\/69282232-f726-4760-9743-73373c5ee43f\/chrome-lite-pages.png\">Large preview<\/a>)<br \/>\n    <\/figcaption><\/figure>\n<p>I\u2019d love to try it out \u2014 apparently it <a href=\"https:\/\/www.chromestatus.com\/feature\/4775088607985664\">disables scripts<\/a>, <a href=\"https:\/\/www.chromestatus.com\/feature\/6072546726248448\">replaces images with placeholders<\/a>, <a href=\"https:\/\/www.chromestatus.com\/feature\/4510564810227712\">prevents loading of non-critical resources<\/a>\u00a0and <a href=\"https:\/\/www.chromestatus.com\/feature\/5076871637106688\">shows offline copies of pages<\/a> if one is available on the device. This <a href=\"https:\/\/www.ghacks.net\/2019\/04\/24\/google-deprecates-chrome-data-saver-extension-for-the-desktop\/\">saves up to 60% of data<\/a>. However, <a href=\"https:\/\/support.google.com\/chrome\/answer\/2392284\">it isn\u2019t available in private (Incognito) mode<\/a>, which hints at some of the privacy concerns surrounding proxy browsers.<\/p>\n<p>Lite mode shares the HTTPS URL with Google, therefore it makes sense that this mode isn\u2019t available in Incognito. However other information such as cookies, login information, and personalised page content is\u00a0<em>not<\/em> shared with Google \u2014\u00a0<a href=\"https:\/\/www.ghacks.net\/2019\/04\/24\/google-deprecates-chrome-data-saver-extension-for-the-desktop\/\">according to ghacks.net<\/a>\u00a0\u2014\u00a0and \u201cnever breaks secure connections between Chrome and a website\u201d. One wonders why seemingly none of these data-saving services are allowed on iOS (and there is <a href=\"https:\/\/www.phonearena.com\/news\/Google-Chrome-update-Data-Saver-Lite-mode-Android_id115558\">no news as to whether Lite mode will ever become available on iOS<\/a>).<\/p>\n<p>Data saver proxies require a great deal of trust; your browsing activity, cookies and other sensitive information are entrusted to some server, often in another country. Many proxies simply won\u2019t work anymore because a lot of sites have moved to HTTPS, meaning initiatives such as Turbo mode have become a largely \u201c<a href=\"https:\/\/forums.opera.com\/topic\/32749\/turbo-mode-disappear-in-opera-60-0\/3\">useless feature<\/a>\u201c. HTTPS prevents this kind of man-in-the-middle behaviour, which is a good thing, although it has meant the demise of some of these proxy services and has made sites <a href=\"https:\/\/meyerweb.com\/eric\/thoughts\/2018\/08\/07\/securing-sites-made-them-less-accessible\/\">less accessible to those on poor connections<\/a>.<\/p>\n<p>I was unable to find any OSX or iOS compatible data-saving tool except for <a href=\"https:\/\/addons.mozilla.org\/en-US\/firefox\/addon\/bandwidth-hero\/\">Bandwidth Hero<\/a> for Firefox (which requires setting up your own data compression service \u2014 far beyond the technical capabilities of most users!) and <a href=\"https:\/\/chrome.google.com\/webstore\/detail\/skyzip-proxy\/hbgknjagaclofapkgkeapamhmglnbphi\">skyZIP Proxy<\/a>\u00a0(which, last updated in 2017 and riddled with typos, I just couldn\u2019t bring myself to trust).<\/p>\n<h3>Conclusion<\/h3>\n<p>Reducing the data footprint of your website goes hand in hand with improving frontend performance. It is the single most reliable thing you can do to speed up your site.<\/p>\n<p>In addition to the cost of data, there are lots of good reasons to focus on performance, as described in a <a href=\"https:\/\/technology.blog.gov.uk\/2019\/04\/18\/why-we-focus-on-frontend-performance\/\">GOV.UK blog post on the subject<\/a>:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.thinkwithgoogle.com\/marketing-resources\/data-measurement\/mobile-page-speed-new-industry-benchmarks\/\">53% of users will abandon a mobile site<\/a>\u00a0if it takes more than 3 seconds to load.<\/li>\n<li><a href=\"http:\/\/www.tecnostress.it\/wp-content\/uploads\/2010\/02\/final_webstress_survey_report_229296.pdf\">People have to concentrate 50% more<\/a> when trying to complete a simple task on a website using a slow connection.<\/li>\n<li>More performant web pages are better for the battery life of the user\u2019s device, and typically require less power on the server to deliver. A performant site is good for the environment.<\/li>\n<\/ul>\n<p>We don\u2019t have the power to change the global cost of data inequality. But we do have the power to lessen its impact, improving the experience for everyone in the process.<\/p>\n<div>\n  <img decoding=\"async\" src=\"http:\/\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/logo-red-22.png\" alt=\"Smashing Editorial\"><span>(yk,ra)<\/span>\n<\/div>\n<\/article>\n<p class=\"wpematico_credit\"><small>Powered by <a href=\"http:\/\/www.wpematico.com\" target=\"_blank\">WPeMatico<\/a><\/small><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I Used The Web For A Day On A 50 MB Budget I Used The Web For A Day On A 50 MB Budget Chris Ashton 2019-07-29T14:00:59+02:002019-07-30T11:06:47+00:00 This article is part of a series in which I attempt to use the web under various constraints, representing a given demographic of user. I hope to raise&#8230;<a class=\"moretag\" href=\"https:\/\/www.taterboy.com\/blog\/2019\/07\/i-used-the-web-for-a-day-on-a-50-mb-budget\/\"> Read the full article&#8230;<\/a><\/p>\n","protected":false},"author":4,"featured_media":68645,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[371],"tags":[],"class_list":["post-68644","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-user-experience"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"I Used The Web For A Day On A 50 MB BudgetI Used The Web For A Day On A 50 MB Budget Chris Ashton 2019-07-29T14:00:59+02:002019-07-30T11:06:47+00:00This article is part of a series in which I attempt to use the web under various constraints, representing a given demographic of user. I hope to raise the profile\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Guest Contribution\"\/>\n\t<meta name=\"keywords\" content=\"user experience\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.taterboy.com\/blog\/2019\/07\/i-used-the-web-for-a-day-on-a-50-mb-budget\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Design for Immersive Technologies | User Experience for Games, Virtual Reality (VR) and Augmented\/Mixed Reality (AR\/MR)\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"I Used The Web For A Day On A 50 MB Budget | Design for Immersive Technologies\" \/>\n\t\t<meta property=\"og:description\" content=\"I Used The Web For A Day On A 50 MB BudgetI Used The Web For A Day On A 50 MB Budget Chris Ashton 2019-07-29T14:00:59+02:002019-07-30T11:06:47+00:00This article is part of a series in which I attempt to use the web under various constraints, representing a given demographic of user. I hope to raise the profile\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.taterboy.com\/blog\/2019\/07\/i-used-the-web-for-a-day-on-a-50-mb-budget\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-07-30T11:18:04+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-07-30T11:18:04+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"I Used The Web For A Day On A 50 MB Budget | Design for Immersive Technologies\" \/>\n\t\t<meta name=\"twitter:description\" content=\"I Used The Web For A Day On A 50 MB BudgetI Used The Web For A Day On A 50 MB Budget Chris Ashton 2019-07-29T14:00:59+02:002019-07-30T11:06:47+00:00This article is part of a series in which I attempt to use the web under various constraints, representing a given demographic of user. I hope to raise the profile\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/i-used-the-web-for-a-day-on-a-50-mb-budget\\\/#article\",\"name\":\"I Used The Web For A Day On A 50 MB Budget | Design for Immersive Technologies\",\"headline\":\"I Used The Web For A Day On A 50 MB Budget\",\"author\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#organization\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/www.taterboy.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/07\\\/01-i-used-the-web-for-a-day-on-a-50-mb-budget.png?fit=400%2C89&ssl=1\",\"width\":400,\"height\":89},\"datePublished\":\"2019-07-30T04:18:04-07:00\",\"dateModified\":\"2019-07-30T04:18:04-07:00\",\"inLanguage\":\"en-US\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/i-used-the-web-for-a-day-on-a-50-mb-budget\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/i-used-the-web-for-a-day-on-a-50-mb-budget\\\/#webpage\"},\"articleSection\":\"User Experience\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/i-used-the-web-for-a-day-on-a-50-mb-budget\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.taterboy.com\\\/blog\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/category\\\/user-experience\\\/#listItem\",\"name\":\"User Experience\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/category\\\/user-experience\\\/#listItem\",\"position\":2,\"name\":\"User Experience\",\"item\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/category\\\/user-experience\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/i-used-the-web-for-a-day-on-a-50-mb-budget\\\/#listItem\",\"name\":\"I Used The Web For A Day On A 50 MB Budget\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/i-used-the-web-for-a-day-on-a-50-mb-budget\\\/#listItem\",\"position\":3,\"name\":\"I Used The Web For A Day On A 50 MB Budget\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/category\\\/user-experience\\\/#listItem\",\"name\":\"User Experience\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#organization\",\"name\":\"Design for Immersive Technologies\",\"description\":\"User Experience for Games, Virtual Reality (VR) and Augmented\\\/Mixed Reality (AR\\\/MR)\",\"url\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/#author\",\"url\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/\",\"name\":\"Guest Contribution\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/i-used-the-web-for-a-day-on-a-50-mb-budget\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d2aad73eb0f48c67b141e9fc978a0e498969791ed623346e361d02d19775b0bb?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"Guest Contribution\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/i-used-the-web-for-a-day-on-a-50-mb-budget\\\/#webpage\",\"url\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/i-used-the-web-for-a-day-on-a-50-mb-budget\\\/\",\"name\":\"I Used The Web For A Day On A 50 MB Budget | Design for Immersive Technologies\",\"description\":\"I Used The Web For A Day On A 50 MB BudgetI Used The Web For A Day On A 50 MB Budget Chris Ashton 2019-07-29T14:00:59+02:002019-07-30T11:06:47+00:00This article is part of a series in which I attempt to use the web under various constraints, representing a given demographic of user. I hope to raise the profile\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/i-used-the-web-for-a-day-on-a-50-mb-budget\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/author\\\/guestcontribution\\\/#author\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/www.taterboy.com\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/07\\\/01-i-used-the-web-for-a-day-on-a-50-mb-budget.png?fit=400%2C89&ssl=1\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/i-used-the-web-for-a-day-on-a-50-mb-budget\\\/#mainImage\",\"width\":400,\"height\":89},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/2019\\\/07\\\/i-used-the-web-for-a-day-on-a-50-mb-budget\\\/#mainImage\"},\"datePublished\":\"2019-07-30T04:18:04-07:00\",\"dateModified\":\"2019-07-30T04:18:04-07:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/\",\"name\":\"Design for Immersive Technologies\",\"description\":\"User Experience for Games, Virtual Reality (VR) and Augmented\\\/Mixed Reality (AR\\\/MR)\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.taterboy.com\\\/blog\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"I Used The Web For A Day On A 50 MB Budget | Design for Immersive Technologies","description":"I Used The Web For A Day On A 50 MB BudgetI Used The Web For A Day On A 50 MB Budget Chris Ashton 2019-07-29T14:00:59+02:002019-07-30T11:06:47+00:00This article is part of a series in which I attempt to use the web under various constraints, representing a given demographic of user. I hope to raise the profile","canonical_url":"https:\/\/www.taterboy.com\/blog\/2019\/07\/i-used-the-web-for-a-day-on-a-50-mb-budget\/","robots":"max-image-preview:large","keywords":"user experience","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/i-used-the-web-for-a-day-on-a-50-mb-budget\/#article","name":"I Used The Web For A Day On A 50 MB Budget | Design for Immersive Technologies","headline":"I Used The Web For A Day On A 50 MB Budget","author":{"@id":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/#author"},"publisher":{"@id":"https:\/\/www.taterboy.com\/blog\/#organization"},"image":{"@type":"ImageObject","url":"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/01-i-used-the-web-for-a-day-on-a-50-mb-budget.png?fit=400%2C89&ssl=1","width":400,"height":89},"datePublished":"2019-07-30T04:18:04-07:00","dateModified":"2019-07-30T04:18:04-07:00","inLanguage":"en-US","mainEntityOfPage":{"@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/i-used-the-web-for-a-day-on-a-50-mb-budget\/#webpage"},"isPartOf":{"@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/i-used-the-web-for-a-day-on-a-50-mb-budget\/#webpage"},"articleSection":"User Experience"},{"@type":"BreadcrumbList","@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/i-used-the-web-for-a-day-on-a-50-mb-budget\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog#listItem","position":1,"name":"Home","item":"https:\/\/www.taterboy.com\/blog","nextItem":{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/#listItem","name":"User Experience"}},{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/#listItem","position":2,"name":"User Experience","item":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/","nextItem":{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/i-used-the-web-for-a-day-on-a-50-mb-budget\/#listItem","name":"I Used The Web For A Day On A 50 MB Budget"},"previousItem":{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/i-used-the-web-for-a-day-on-a-50-mb-budget\/#listItem","position":3,"name":"I Used The Web For A Day On A 50 MB Budget","previousItem":{"@type":"ListItem","@id":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/#listItem","name":"User Experience"}}]},{"@type":"Organization","@id":"https:\/\/www.taterboy.com\/blog\/#organization","name":"Design for Immersive Technologies","description":"User Experience for Games, Virtual Reality (VR) and Augmented\/Mixed Reality (AR\/MR)","url":"https:\/\/www.taterboy.com\/blog\/"},{"@type":"Person","@id":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/#author","url":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/","name":"Guest Contribution","image":{"@type":"ImageObject","@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/i-used-the-web-for-a-day-on-a-50-mb-budget\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/d2aad73eb0f48c67b141e9fc978a0e498969791ed623346e361d02d19775b0bb?s=96&d=mm&r=g","width":96,"height":96,"caption":"Guest Contribution"}},{"@type":"WebPage","@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/i-used-the-web-for-a-day-on-a-50-mb-budget\/#webpage","url":"https:\/\/www.taterboy.com\/blog\/2019\/07\/i-used-the-web-for-a-day-on-a-50-mb-budget\/","name":"I Used The Web For A Day On A 50 MB Budget | Design for Immersive Technologies","description":"I Used The Web For A Day On A 50 MB BudgetI Used The Web For A Day On A 50 MB Budget Chris Ashton 2019-07-29T14:00:59+02:002019-07-30T11:06:47+00:00This article is part of a series in which I attempt to use the web under various constraints, representing a given demographic of user. I hope to raise the profile","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/www.taterboy.com\/blog\/#website"},"breadcrumb":{"@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/i-used-the-web-for-a-day-on-a-50-mb-budget\/#breadcrumblist"},"author":{"@id":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/#author"},"creator":{"@id":"https:\/\/www.taterboy.com\/blog\/author\/guestcontribution\/#author"},"image":{"@type":"ImageObject","url":"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/01-i-used-the-web-for-a-day-on-a-50-mb-budget.png?fit=400%2C89&ssl=1","@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/i-used-the-web-for-a-day-on-a-50-mb-budget\/#mainImage","width":400,"height":89},"primaryImageOfPage":{"@id":"https:\/\/www.taterboy.com\/blog\/2019\/07\/i-used-the-web-for-a-day-on-a-50-mb-budget\/#mainImage"},"datePublished":"2019-07-30T04:18:04-07:00","dateModified":"2019-07-30T04:18:04-07:00"},{"@type":"WebSite","@id":"https:\/\/www.taterboy.com\/blog\/#website","url":"https:\/\/www.taterboy.com\/blog\/","name":"Design for Immersive Technologies","description":"User Experience for Games, Virtual Reality (VR) and Augmented\/Mixed Reality (AR\/MR)","inLanguage":"en-US","publisher":{"@id":"https:\/\/www.taterboy.com\/blog\/#organization"}}]},"og:locale":"en_US","og:site_name":"Design for Immersive Technologies | User Experience for Games, Virtual Reality (VR) and Augmented\/Mixed Reality (AR\/MR)","og:type":"article","og:title":"I Used The Web For A Day On A 50 MB Budget | Design for Immersive Technologies","og:description":"I Used The Web For A Day On A 50 MB BudgetI Used The Web For A Day On A 50 MB Budget Chris Ashton 2019-07-29T14:00:59+02:002019-07-30T11:06:47+00:00This article is part of a series in which I attempt to use the web under various constraints, representing a given demographic of user. I hope to raise the profile","og:url":"https:\/\/www.taterboy.com\/blog\/2019\/07\/i-used-the-web-for-a-day-on-a-50-mb-budget\/","article:published_time":"2019-07-30T11:18:04+00:00","article:modified_time":"2019-07-30T11:18:04+00:00","twitter:card":"summary","twitter:title":"I Used The Web For A Day On A 50 MB Budget | Design for Immersive Technologies","twitter:description":"I Used The Web For A Day On A 50 MB BudgetI Used The Web For A Day On A 50 MB Budget Chris Ashton 2019-07-29T14:00:59+02:002019-07-30T11:06:47+00:00This article is part of a series in which I attempt to use the web under various constraints, representing a given demographic of user. I hope to raise the profile"},"aioseo_meta_data":{"post_id":"68644","title":null,"description":null,"keywords":null,"keyphrases":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_custom_url":null,"og_image_custom_fields":null,"og_custom_image_width":null,"og_custom_image_height":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"location":null,"local_seo":null,"created":"2021-02-07 18:44:24","updated":"2026-09-01 17:48:03","focus_keyword":null,"additional_keywords":null,"truseo_locale":null,"primary_term":null,"og_image_url":null,"og_image_width":null,"og_image_height":null,"twitter_image_url":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"limit_modified_date":false,"ai":null,"breadcrumb_settings":null,"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.taterboy.com\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/\" title=\"User Experience\">User Experience<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tI Used The Web For A Day On A 50 MB Budget\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.taterboy.com\/blog"},{"label":"User Experience","link":"https:\/\/www.taterboy.com\/blog\/category\/user-experience\/"},{"label":"I Used The Web For A Day On A 50 MB Budget","link":"https:\/\/www.taterboy.com\/blog\/2019\/07\/i-used-the-web-for-a-day-on-a-50-mb-budget\/"}],"jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8wzr5-hRa","jetpack_featured_media_url":"https:\/\/i0.wp.com\/www.taterboy.com\/blog\/wp-content\/uploads\/2019\/07\/01-i-used-the-web-for-a-day-on-a-50-mb-budget.png?fit=400%2C89&ssl=1","_links":{"self":[{"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/posts\/68644","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/comments?post=68644"}],"version-history":[{"count":0,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/posts\/68644\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/media\/68645"}],"wp:attachment":[{"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/media?parent=68644"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/categories?post=68644"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.taterboy.com\/blog\/wp-json\/wp\/v2\/tags?post=68644"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}