List of Figures

Chapter 1. Understanding web performance

Figure 1.1. The average rankings of all pages on the Legendary Tones website according to its page download time by Google. Lower values are better.

Figure 1.2. A user’s request for example.com. The user sends the request for the web page via a browser and then must wait for the server to gather its response and send it. After the server sends the response, the user receives the web page in the browser.

Figure 1.3. The anatomy of an HTTP request to example.com.

Figure 1.4. Steps to get index.html from a web server

Figure 1.5. The client’s website in the web browser running from your local machine

Figure 1.6. The location of the Network tab in the Google Chrome Developer Tools window. You can simulate internet connection speeds by using the throttling menu.

Figure 1.7. The Record button must be in the enabled state (red) before you can generate a waterfall chart of assets. The Disable Cache check box should also be selected so that no caching is done when you reload the page to measure the results of your work.

Figure 1.8. A waterfall chart generated for your client’s website. At the top, you can see the request for index.html, followed by the site’s CSS, JavaScript, and images. Each bar represents a request for a site asset. The bars are positioned on the x-axis according to the time they began downloading on the left, and the time they have finished downloading on the right. The length of a bar corresponds to the amount of time it takes for the asset to be requested and downloaded by the web browser.

Figure 1.9. Minification of a CSS rule. In this example, a CSS rule is minified from 98 bytes down to 77, which represents a 21% reduction. When this concept is applied to all text assets on a site, the reductions can total many kilobytes.

Figure 1.10. Load times of the client’s website on the Regular 3G network throttling profile before and after minification. Improvements range anywhere from 31% to 41%, depending on the visitor’s device.

Figure 1.11. The process of server compression

Figure 1.12. Load times of the client’s site on the Regular 3G throttling profile before and after applying compression. Depending on the visitor’s device, load times improve anywhere from 18% to 32%.

Figure 1.13. Image optimization in action on a PNG image. Optimizing images in this manner uses a re-encoding technique that discards unnecessary data from the image, but doesn’t noticeably impact the image’s visual quality.

Figure 1.14. TinyPNG compressing the client website’s images and reporting a 61% reduction of total size

Figure 1.15. Load times of the client’s website on the Regular 3G network throttling profile before and after optimizing images. Depending on the visitor’s device, load times improve anywhere from 23% to 53%.

Figure 1.16. Load times of the client’s website on the Regular 3G throttling profile before and after all optimizations were made. Load times improve approximately 70% for all visitors on all devices.

Chapter 2. Using assessment tools

Figure 2.1. Google PageSpeed Insights checks two aspects of page speed: the load time of above-the-fold content, which is what the user sees immediately upon visiting a page, and the load time of the entire page.

Figure 2.2. Google PageSpeed Insights results for the mobile view of a website. A user enters a URL and gets performance tips grouped by severity for both mobile and desktop states.

Figure 2.3. The PageSpeed Insights report for the client website from chapter 1 prior to (left) and after (right) your optimizations.

Figure 2.4. PageSpeed Insights reporting information can be accessed in Google Analytics by navigating to the Behavior section on the left menu and clicking the Speed Suggestions link.

Figure 2.5. The reporting table of performance statistics in Google Analytics. Note the two rightmost columns with PageSpeed Insights–specific data and links to reports for associated page URLs.

Figure 2.6. The process of a web browser’s request to a web server. Latency occurs in each step of the process. The amount of time between the instant the user makes a request to the time the response arrives is known as Time to First Byte (TTFB).

Figure 2.7. Timing information for a site asset. The TTFB in this example is 174.56 ms.

Figure 2.8. The Safari Developer Tools can be used only if the Develop option is visible in the menu bar when the Safari web browser window is in focus. If you don’t see this menu, you have to enable the developer tools.

Figure 2.9. You can enable the Safari Developer Tools by choosing Safari > Preferences from the menu bar. In the window that appears, click the Advanced tab and select the check box.

Figure 2.10. The network request information for a website in the Network tab in Safari’s Developer Tools. Note the lack of a waterfall graph in this view in favor of columns for timing information.

Figure 2.11. HTTP headers are sent by the browser in the initial request and by the server in its response. In this figure, a simplified set of headers is shown. The network inspection utilities in the developer tools for every browser allow the user to examine these headers.

Figure 2.12. Viewing HTTP headers in Chrome’s Developer Tools. Accessing HTTP headers for an asset can be done by clicking the asset name. A new pane to the right opens, with the header information contained within the Headers tab.

Figure 2.13. The Content-Encoding response header from the web server lets you know that the asset is compressed, as well as the compression algorithm used (gzip in this example).

Figure 2.14. Viewing HTTP headers in Microsoft Edge requires the user to click a small toggle button at the farright side of the window in the Network tab.

Figure 2.15. The page-rendering process.

Figure 2.16. The Timeline tool in the populated state.

Figure 2.17. The breakdown of session activity as recorded by the Timeline tool

Figure 2.18. An isolated call stack from the flame chart view in the Timeline tool. The top event is a loading event where the HTML was parsed. Underneath it are events originating from it, such as the DOMContentLoaded event that fires when the DOM is ready, and scripting and rendering events.

Figure 2.19. The breakdown of a scripting event. You can see information related to the event, such as the amount of CPU time used, the event type, and its origination. This data is also visualized in a pie chart.

Figure 2.20. A timeline recording of the modal opening on the client website. A range of janky frames is denoted with red markers in the activity overview, and highlighted in red and clickable in the flame chart.

Figure 2.21. The summary view of a janky frame. Note the explicit warning and the low frame rate.

Figure 2.22. The event log filtered by scripting events. The text box can be used to filter events by the contents of their activity, filtered by a specific length of time in the duration drop-down, and/or by type.

Figure 2.23. Modal animation performance after CSS transitions have been implemented. Janky frames still exist, but much less so than before, resulting in an overall improved experience.

Figure 2.24. CPU usage summary of jQuery animations (left) compared to CSS transitions (right)

Figure 2.25. A marker added to the timeline. The associated call stack is selected, and the timestamp event call is shown in the event log.

Figure 2.26. An annotated overview of Microsoft Edge’s performance profiler

Figure 2.27. The results of two benchmarks you’ve run of jQuery’s DOM selection versus that of the native document.querySelector method. Results are circled.

Figure 2.28. The device simulation mode in Chrome viewing the Manning Publications website

Figure 2.29. The Chrome device list showing an open web page on a connected Android phone

Figure 2.30. The Developer Tools profiling rendering activity of a page on an Android phone. In this view, the device’s display is mirrored on the host machine, and the Developer Tools are focused on the device’s current page rather than a session active on the desktop.

Figure 2.31. The throttling profiles that ship with Chrome, with the option to add custom profiles

Figure 2.32. Adding a new throttling profile in Chrome. The profile requires four bits of information: a profile name, the download and upload speeds (inKbits/sec), and the latency in milliseconds.

Figure 2.33. Your new custom network throttling profile is now in the list.

Chapter 3. Optimizing CSS

Figure 3.1. An example of shorthand CSS via the font property

Figure 3.2. The margin shorthand property takes one to four values: those for margin-top, marginright, margin-bottom, and margin-left.

Figure 3.3. An example of an overly specific CSS selector (left) versus a more succinct one (right). The selector at the left is 67 characters, whereas the one at the right is at 12 characters.

Figure 3.4. An example of the DRY principle. Two selectors have the same background property. To save space and eliminate redundancy, the background property and the selectors are combined.

Figure 3.5. A user navigation flow to pages with CSS segmented by page template. The browser downloads only the CSS it needs for the current page.

Figure 3.6. The Behavior section of the left-hand menu in Google Analytics. The visitor flows can be seen by clicking the Behavior Flow link in the Behavior submenu.

Figure 3.7. The visitor flow chart in Google Analytics. Starting at the left, you see where users enter the site. In this case, you see that the vast majority of users are entering on the site’s main page. Few visitors click through to the subpages.

Figure 3.8. The download customization screen on the Twitter Bootstrap website. Bootstrap allows the developer to specify which parts of the framework the user wants in a custom download.

Figure 3.9. Mobile-first versus desktop-first responsive design flows

Figure 3.10. The trend of internet traffic on mobile devices versus laptop devices. Toward the end of 2015, nearly half of all traffic on the internet occurred on mobile devices. This trend is continuing (Data from StatCounter Global Stats).

Figure 3.11. The flow of layout complexity across breakpoints on a mobile-first website

Figure 3.12. A responsive site on a mobile device without the <meta> viewport tag (left) and the same site with it (right). Even though the site pictured is a mobile-first responsive site, it won’t display in the proper breakpoint without this crucial tag in place, and the user will be forced to zoom out to view the entire site.

Figure 3.13. The results page of Google’s Mobile-Friendly Test tool after examining a website

Figure 3.14. Downloads for two style sheets are serialized one after the other because of an @import directive in styles.css that requests fonts.css.

Figure 3.15. Two requests for style sheets made by using the <link> tag. The <link> tags are found by the browser after downloading the HTML, and the browser executes these two requests at the same time.

Figure 3.16. A rendering timeline in Chrome showing the Flash of Unstyled Content effect at left. The document eventually renders as intended, but with a brief display of the unstyled content. In this case, the effect is due to a <link> tag referencing a style sheet being placed at the end of the document.

Figure 3.17. Rendering performance at load time of my personal website in Chrome with styles placed in the <head> versus at the end

Figure 3.18. The structure of the test HTML document. The test markup is contained within a div.contentContainer. Within it are four <section> elements arranged in four columns, each containing two <ul> elements with 51 <li> elements. The block of four <section> elements is then repeated approximately 50 times. The total number of elements in each test document is about 21,000.

Figure 3.19. The performance of the CSS selectors test in Chrome. On the left are the selector types, and on the bottom is the amount of time each selector type took to complete the test in seconds. All values are the sum of rendering and painting processes.

Figure 3.20. Benchmark results of box model layout performance versus flexbox layout in Chrome. Lower is better.

Figure 3.21. The .box element on the page before and after a transition on its border-radius property

Chapter 4. Understanding critical CSS

Figure 4.1. A depiction of above- and below-the-fold content on an array of devices. The above-the-fold content begins at the top of a website and ends at the bottom of the screen. Anything that’s out of the browser’s view is below the fold.

Figure 4.2. Chrome’s Timeline profiler when the document’s first painting event occurs. The event can be found under the Event Log tab by filtering out all but the painting events.

Figure 4.3. Chrome’s Timeline profiler showing an improved paint time after the contents of the site’s CSS have been inlined into the HTML

Figure 4.4. Inline styles loaded for above-the-fold content. The CSS for the above-the-fold content is inlined into the HTML for faster parsing, which translates into a faster Time to First Paint.

Figure 4.5. The preload resource hint loading external CSS for below-the-fold content. This method loads an external style sheet in a way that doesn’t block rendering. When the CSS has finished loading, an onload event fires and flips the rel value of the <link> so that the styles render.

Figure 4.6. The recipe website in Chrome. This is the tablet breakpoint at roughly 750 pixels wide.

Figure 4.7. A chart of common device resolutions on mydevice.io, sorted in descending order by CSS height. The site also offers information for devices other than mobile phones. The physical resolution differs from CSS resolution in that they’re both normalized to the same scale for consistency.

Figure 4.8. The VisualFold! bookmarklet in action. The user enters a number in a dialog box (left) indicating the desired location of a guideline to be drawn on the page (right). This assists the user in locating the fold. By resizing the window, the user can see how the content flows with respect to this line.

Figure 4.9. The mobile breakpoint of the page with labels of the critical components

Figure 4.10. The large breakpoint with components labeled that were below the fold on the mobile version

Figure 4.11. The appearance of the recipe website after you’ve inlined the header selector CSS into the HTML. It’s partially styled, but much is still missing.

Figure 4.12. The critical CSS after all of the header styles have been inlined into index.html

Figure 4.13. Time to first paint performance in Google Chrome before and after implementing critical CSS

Figure 4.14. Time to First Paint in Mobile Safari on an iPhone 6S over a remote shared host before and after prioritizing critical CSS

Figure 4.15. A modularized approach to critical CSS. Template A and Template B have their own critical CSS that’s inlined only for those pages, but both inline globally common critical styles.

Chapter 5. Making images responsive

Figure 5.1. Two examples of scaling an image to a mobile phone. At the top, a 170-KB image with a width of 1440 pixels is scaled down to the width of the phone’s high DPI display. At the bottom, a 41-KB image with a width of 750 pixels is delivered to the screen without having to be scaled; this process is more efficient.

Figure 5.2. A comparison of rendering and painting times for a single image in Chrome. For the scaling scenario, the source image of 1440 x 900 is scaled to fit a container 375 pixels wide. In the no-scaling scenario, an image resized to fit the container is used and triggers no scaling. Rendering and painting times are faster with no scaling.

Figure 5.3. A 16 x 16 raster image of a YouTube favicon. On the left is the native size of the image, and on the right is the enlarged version. Each pixel is part of a two-dimensional grid.

Figure 5.4. JPEG images in use on the popular photo cataloging and sharing site Flickr. Photographic content is best suited to the JPEG format.

Figure 5.5. A comparison of the same image in uncompressed (TIFF) and compressed (JPEG) formats with their respective file sizes. The JPEG version has some subtle degradation at a quality setting of 30, but is acceptable for this scenario.

Figure 5.6. The Facebook logo is a PNG image, which is a lossless image format. PNG images are well suited for lossless formats.

Figure 5.7. A comparison of lossless image-compression methods. The differences between the uncompressed and full-color PNG and WebP versions are imperceptible, whereas the 8-bit lossless image is throttled down to 256 colors.

Figure 5.8. A cartoon vector image at different sizes. Notice that the larger version doesn’t lose any visual quality as it scales up. This is the primary advantage of vector images over raster images.

Figure 5.9. The Legendary Tones website as it appears in the browser

Figure 5.10. The masthead background image at the 480-pixel (30em) breakpoint before (left) and after (right) adding the new background image. Note the improved visual quality in the after image.

Figure 5.11. An enlarged visual representation of graphics on standard displays versus high DPI displays

Figure 5.12. A comparison of two versions of a background image on two display types. On the left, a background image intended for use on standard displays appears on a high DPI display. On the right, the proper resolution image is used for the high DPI display, creating a better visual experience.

Figure 5.13. A comparison of image behaviors with and without max-width restrictions. The example on the left is the default behavior: If the image is larger than its container, it’ll exceed the boundaries. On the right is an image with a max-width of 100%, which constricts the image to the width of the container.

Figure 5.14. The new feature image as it appears on the Legendary Tones website

Figure 5.15. The effect of the sizes attribute on the article image in Google Chrome. On the 704 px breakpoint, the image takes up 50% of the viewport, at the 480 px breakpoint the image takes up 75%, and the default image behavior below 480 px is to occupy the entire viewport.

Figure 5.16. An example of art direction across a trio of images. In the largest version, the subject has more context and surrounding details, because larger screens can accommodate more. As the screen width decreases, the image is cropped differently so the subject is still visible on smaller screens.

Figure 5.17. Image behaviors on the Legendary Tones website. On small screens (left), the image centers in the viewport and breaks between paragraphs. On large screens (right), the image floats to the right, and the text wraps around it.

Figure 5.18. Image behaviors of the website after modifications to the <picture> element. Note that small screens (left) offer a different treatment of the image based on the screen resolution.

Figure 5.19. Conditional loading of Picturefill as seen in two browsers’ network request inspectors. On the left is a version of Safari that doesn’t support the <picture> or srcset features and therefore loads Picturefill. On the right is Chrome, which fully supports these features and therefore skips loading Picturefill.

Chapter 6. Going further with images

Figure 6.1. An image sprite of various social media icons

Figure 6.2. The anatomy of the svg-sprite command as used to generate an SVG sprite with LESS mixins

Figure 6.3. The newly generated image sprite with annotations showing the names of the standalone files prior to being added to the sprite

Figure 6.4. An overview of images on the recipe website that are or aren’t candidates for inclusion in an image sprite. Iconography is marked for inclusion, whereas imagery such as recipe images and ads isn’t.

Figure 6.5. SVG files can be converted to PNG by dragging and dropping SVG files on the Grumpicon beast (or by browsing to them).

Figure 6.6. The client’s recipe website as it appears in the tablet breakpoint

Figure 6.7. A comparison of the unoptimized (left) and optimized versions of chicken-tacos-2x.jpg. The optimized version is about 55% smaller, but the visual differences are virtually imperceptible.

Figure 6.8. Website load times before and after the optimization of images for the recipe website using the Good 3G networking throttling profile in Google Chrome

Figure 6.9. A comparison of the logo.png and logo-2x.png files before and after optimization

Figure 6.10. The Weekly Timber logo before (left) and after optimization with svgo using the default options

Figure 6.11. The Weekly Timber logo before (left) and after (right) optimizing even further by reducing decimal precision with svgo to a value of 1

Figure 6.12. An examination of the unoptimized logo.svg (left) compared to an overoptimized version. All precision is stripped from the SVG shapes, resulting in a loss of fidelity, especially with Bézier curves.

Figure 6.13. A JPEG optimized by using imagemin’s jpeg-recompress plugin (left) compared to a WebP image encoded from the unoptimized JPEG at a quality setting of 40.

Figure 6.14. A comparison of load times on the recipe website of JPEG and WebP images on standard and high DPI screens. The WebP images offer better loading performance in comparison to both the optimized and unoptimized JPEG images.

Figure 6.15. A comparison of unoptimized PNGs, optimized PNGs, and lossless WebP images

Figure 6.16. Safari failing to display a WebP image

Figure 6.17. The network request inspector for two web browsers for our recipe collection page. Chrome (left) can use the WebP images, but Firefox (right) can’t, so it falls back to image types it supports.

Figure 6.18. An audit of which images make sense to lazy load and which ones don’t

Figure 6.19. The buffer property specifies how far out of the viewport the lazy loader will look for images to load. By extending what the lazy loader looks for beyond the viewport, you can begin loading images as you approach them to give the browser a head start.

Figure 6.20. The position calculations of the inViewport method, and how they relate to the viewport and the targeted image element. In this case, the calculation of the viewport height plus the amount of buffer space given exceeds the top boundary of the image element, resulting in a return value of true.

Figure 6.21. The network waterfall graph showing lazy loaded images

Figure 6.22. The effect of lazy loading a script on browsers with JavaScript turned off. The images never load because the JavaScript never runs.

Figure 6.23. The <noscript> tag at work. Both the image placeholder and the image loaded in the <noscript> tag are visible because the image placeholder is never hidden when JavaScript is disabled.

Chapter 7. Faster fonts

Figure 7.1. The client’s content page with all of the font weights annotated

Figure 7.2. The process of a user’s browser processing a @font-face cascade. The browser searches for a locally installed version (if specified,) and if it can’t find one, it will iterate through all of the @font-face src() calls for various formats of the same font.

Figure 7.3. The size of the Open Sans Regular font before and after compression. The gains in this example are about 45%, from 212.26 KB to 113.76 KB, over the uncompressed versions. EOT compression ratios are similar.

Figure 7.4. Google subsetting fonts by language

Figure 7.5. A portion of a table of Unicode characters from unicode.org, showing glyphs and their code points. The lowercase p is identified by its Unicode code point of U+0070.

Figure 7.6. Subsetting a font with pyftsubset. The input file is specified first, followed by the Unicode range of characters you want to subset from the input font, and then the output filename. The last option is used to preserve all name table entries, which ensures better compatibility with the font converters.

Figure 7.7. Load times before and after subsetting fonts. Load times are improved by well over 200%. Load times include load times for all assets on site. True-Type fonts were compressed by the server in these trials. (EOT omitted due to incompatibility; file sizes are nearly identical to TTF.)

Figure 7.8. The Basic Latin font subsets are loaded on the Russian version of the page, despite having a unicode-range property set to use these fonts only for pages displaying characters from the Basic Latin subset.

Figure 7.9. The fonts downloaded by the Russian version of the page (left) as compared to the English version (right), even though they both use the same style sheet. The unicode-range property detects whether any characters in the document exist in the defined ranges, and if so, the related @font-face resource is served up.

Figure 7.10. Cyrillic subsets loading on the English version of the page, regardless of the unicode-range property. The behavior shown is in Safari.

Figure 7.11. The contents of the network tab in Safari on both the English (left) and Russian (right) versions of the content page, with your fallback script enabled on each page. The English version downloads only the fonts it needs, whereas the Russian version grabs the additional ru.css and the font subsets contained therein.

Figure 7.12. As a page loads embedded fonts, the text is initially invisible (left) until the fonts fully load, at which point the text styled in those font faces appears.

Figure 7.13. When the download time for a font is too long, the text will eventually become visible, but is unstyled because of the still-loading font resource (left). After all of the fonts load, the text will become styled (right). This is known as FOUT.

Figure 7.14. The toggle button to capture screenshots in Chrome Developer Tools

Chapter 8. Keeping JavaScript lean and fast

Figure 8.1. Browsers read HTML documents from top to bottom. When links to external resources (such as scripts, in this case) are found, the browser stops to parse them. When parsing occurs, rendering is blocked.

Figure 8.2. The Time to First Paint in Chrome for the Coyle Appliance Repair website with <script> tags in the <head> of the document.

Figure 8.3. The Time to First Paint in Chrome for the Coyle Appliance Repair website with the <script> tags at the end of the document

Figure 8.4. A comparison of loading scripts with and without the user of the async attribute. The main difference is that scripts loaded with async won’t wait for other scripts to finish loading before they execute.

Figure 8.5. The async attribute creates a problem in which behaviors.js fails because it executes before its dependency jquery.min.js is available.

Figure 8.6. A race condition between jquery.min.js and behaviors.js always results in a failure, because behaviors.js loads and executes before its dependency is available.

Figure 8.7. The Time to First Paint value in Chrome for the Coyle Appliance Repair website with scripts bundled and loaded using the async attribute

Figure 8.8. A comparison of file sizes of jQuery and its alternatives

Figure 8.9. Performance of jQuery versus its alternatives when selecting an element by its class

Figure 8.10. Performance of jQuery versus its alternatives when toggling a class on an element

Figure 8.11. Performance of jQuery versus its alternative when toggling an attribute on an element

Figure 8.12. The loading of the fetch API polyfill and its timing with the user’s intentions to fire the scheduling modal

Figure 8.13. Normalized performance of various animation methods in Chrome’s Timeline tool

Figure 8.14. The animate function in use, with arguments labeled

Chapter 9. Boosting performance with service workers

Figure 9.1. A service worker operating on its own thread labeled ServiceWorker Thread can be seen at the bottom in this view of Chrome’s Timeline tool.

Figure 9.2. A service worker communicating as a proxy between a user and a web server. The user makes requests, which the service worker can intercept. Depending on how the service worker code is written, assets can be retrieved from the service worker’s CacheStorage cache, or passed through to the web server. The service worker can also write to the cache in specific instances.

Figure 9.3. The service worker installation process. The code checks for the status of service worker support. If the browser supports it, the service worker is installed. If not, the browser does nothing.

Figure 9.4. The behavior that you want to occur when the service worker’s install event is fired

Figure 9.5. The Application tab in Chrome’s Developer Tools showing active service workers for the current site. Click the Service Workers item in the left pane to access this panel.

Figure 9.6. The v1 cache created by your service worker. You can see that the assets you’ve specified in the service worker’s cachedAssets array are present.

Figure 9.7. Selecting the Offline check box in Chrome’s Network panel allows you to simulate what it’s like to be offline without having to disable your network connection.

Figure 9.8. The behavior of the service worker’s fetch event. The user makes a request for an asset, and the service worker steps in to intercept it to see whether the asset is already in the cache. If not, the asset is fetched from the network, and the service worker caches it. If it’s in the cache, it’s pulled from the cache.

Figure 9.9. Network requests intercepted by the service worker will be indicated by a value of “(from ServiceWorker)” in the Size column in Chrome’s network utility.

Figure 9.10. A comparison of the Time to First Paint performance of various caching scenarios on Chrome’s Regular 3G throttling profile. The scenarios are an uncached page, the page when retrieved by the browser cache, and the page when retrieved from the service worker cache.

Figure 9.11. A two-pronged approach for intercepting a network request in a service worker’s fetch event. If the requested asset is an HTML document, you always fetch it from the network and place it in the cache, and serve it from the service worker cache only if you’re offline. If the resource isn’t an HTML document, you always serve from the cache and retrieve it from the network if it’s not in the service worker cache.

Figure 9.12. An orphaned cache entry after updating the style sheet reference. global.css?v=1 is in the cache, whereas the unused global.css entry remains.

Figure 9.13. Your new v2 cache. If you click this, you’ll be able to see the updated cache contents, particularly the global.css?v=1 entry.

Chapter 10. Fine-tuning asset delivery

Figure 10.1. The user makes a request to the server for index.html, and the browser specifies the algorithms that are supported in the Accept-Encoding header. Here, the server replies with the compressed content of index.html, and the compression algorithm used in the response’s Content-Encoding header.

Figure 10.2. The effects of the compression-level setting on overall load times and TTFB when requesting jquery.min.js. Tests were performed on Chrome’s Regular 3G network throttling profile.

Figure 10.3. Compression ratios of PNG, JPEG, and SVG images across all gzip compression levels.

Figure 10.4. Chrome showing support for Brotli compression with the br token

Figure 10.5. Brotli-encoded files can be seen in the network request panel in Chrome by looking for the br token in the Content-Encoding column.

Figure 10.6. Performance of compressing the jQuery library with gzip versus Brotli compression across all comparable compression levels. (A gzip compression level of 0 is the same as no compression, and so is omitted.) Gzip’s maximum compression level is 9, so comparisons to Brotli’s quality settings of 10 and 11 aren’t available.

Figure 10.7. TTFB performance of gzip versus Brotli when compressing the jQuery library

Figure 10.8. A basic overview of the caching process. The user requests index.html, and the server checks whether the asset has changed since the time the user last requested it. If the asset hasn’t changed, the server responds with a 304 Not Modified status and the browser’s cached copy is used. If it has changed, the server responds with a 200 OK status along with a new copy of the requested asset.

Figure 10.9. The load times and data payload of a website on the first uncached visit and on a subsequent visit. The page weight is nearly 98% smaller, and the load time is much faster, all due to caching.

Figure 10.10. A copy of jQuery being retrieved from the local browser cache

Figure 10.11. The effect of the Cache-Control header’s max-age directive and the browser/server interaction that results in its use

Figure 10.12. The basic concept of a CDN. A CDN is a proxy that sits in front of your website and distributes your content to users across the world. The CDN can do this through a network of geographically distributed servers that host your content. Users have their content requests fulfilled by servers that are closest to them.

Figure 10.13. The effects of your cache policy on the Weekly Timber website. The HTML is revalidated from the server on every request, and the server returns a 304 status if the document hasn’t changed on the server. Items reading from the browser cache don’t trigger a return trip to the web server.

Figure 10.14. In a CDN, assets hosted on an origin server are distributed to edge servers, which are servers that are located closer to potential website visitors.

Figure 10.15. A comparison of load times and TTFB for jQuery over several CDNs versus a low-cost shared hosting environment

Figure 10.16. The Network panel in Chrome showing the CDN asset failing to load and the page falling back to the locally hosted version

Figure 10.17. The process of verifying assets by using Subresource Integrity. A user requests an asset from a CDN, and the asset’s safety is determined via a checksum verification process. If the asset is safe, it’s used. If not, the asset is discarded.

Figure 10.18. The format of the integrity attribute. This value starts off with the hashing algorithm (SHA-256, in this case) and is followed by the checksum value for the referenced resource.

Figure 10.19. The effects of the preconnect resource hint when loading jQuery from a CDN on both HTTP and HTTPS

Figure 10.20. Page load times for the Weekly Timber home page when prefetching jQuery versus no prefetching using Chrome’s Regular 4G network throttling profile

Figure 10.21. The Network panel showing jquery-2.2.3.min.js loaded with the preload resource hint. The first line for the jQuery library is from the preload hint, whereas the second occurs when the item is retrieved from the cache. Note the size of 0 bytes on the second entry for jquery-2.2.3.min.js.

Chapter 11. Looking to the future with HTTP/2

Figure 11.1. The 1996 (left) and 2016 (right) incarnation of the Los Angeles Times

Figure 11.2. The head-of-line blocking problem as shown in a batch of nine requests. The first batch of six requests is fulfilled in parallel, but the remaining batch can’t start downloading until the largest file (masthead.jpg) in the first batch finishes downloading. This problem can cause delays in load times.

Figure 11.3. A session ID cookie of 128 bytes distributed across 60 requests, adding up to a total of 7.5 KB of extra data sent to the web server

Figure 11.4. The anatomy of an HTTP/2 request. One connection houses multiple bidirectional streams, which in turn contain multiple messages that request and receive assets. These messages are delimited by frames, which in turn describe the content of messages (headers, response bodies, and so forth).

Figure 11.5. HPACK header compression in action. Headers are stored in an indexed table. Identical headers discovered in later requests for the same page are tied to an index in the table to avoid duplication of that data, whereas headers with new data are stored as new entries in the table.

Figure 11.6. The Network panel in Chrome’s Developer Tools indicating assets transferred over HTTP/2. Assets transferred over HTTP/1 will have the value http/1.1 in this field.

Figure 11.7. The effect on asset downloads on HTTP/1 (left) versus HTTP/2 (right): downloads in HTTP/2 are parallelized more than in HTTP/1, meaning that they begin roughly at the same time.

Figure 11.8. Comparing page-load times on the Weekly Timber website on HTTP/1 versus HTTP/2

Figure 11.9. A comparison of the bytes sent during an HTTP/2 session versus that of an HTTP/1 session

Figure 11.10. Concatenation can reduce caching efficiency. One of four icons in the image sprite is modified, but even though 75% of the file content remains unmodified, the user will be forced to download the entire asset instead of just the changed portion.

Figure 11.11. An example of a data URI. The scheme begins with the data URI, followed by the encoded data’s content type, the name of the encoding scheme, and the encoded data (truncated in this example).

Figure 11.12. The anatomy of a Server Push event: the user requests index.html, and the server responds with a PUSH_PROMISE frame that contains the pushed copy of styles.min.css, as per its configuration.

Figure 11.13. The Network tab in Chrome indicating a pushed asset by way of the Push keyword in the asset’s Initiator column

Figure 11.14. Time to First Paint comparison with and without Server Push for the client website’s CSS

Figure 11.15. The anatomy of an HTTP/2 negotiation. The client requests an asset, and the server then checks whether the browser is capable of using HTTP/2. If so, it proceeds accordingly. If not, the connection downgrades to HTTP/1.

Figure 11.16. The Can I Use website displaying support of HTTP/2 by browser

Figure 11.17. The section to import your site data from Google Analytics

Figure 11.18. The support formula for a feature on Can I Use after Google Analytics data has been imported. All Web Site Data is the data imported from Google Analytics.

Figure 11.19. The <html> tag is modified on the server when the web server downgrades to HTTP/1.

Figure 11.20. The scripts for the client website delivered in concatenated fashion for HTTP/1 browsers

Chapter 12. Automating optimization with gulp

Figure 12.1. An unautomated workflow for compiling LESS into CSS

Figure 12.2. An automated workflow for compiling LESS into CSS. The only tasks the developer has to perform are making and saving changes, while the build system builds the CSS and reloads the page for us.

Figure 12.3. The concept of a stream. In this example, the input is composed of LESS files that are piped into the stream, which then compiles the LESS into CSS and pipes that completed output into a CSS file.

Figure 12.4. An example of data being piped in and out of multiple streams. The first stream compiles the LESS file into CSS, which is then piped into another stream that minifies it.

Figure 12.5. The outline of a task. The task is identified by its name, buildCSS, and begins with a LESS source file named main.less that resides on the disk. This file is piped into a stream that compiles main.less into a CSS file that is outputted from the stream and saved to the disk as styles.css.

Figure 12.6. The build system processes files from a source folder (src in this example) and processes them and writes the output to the distribution folder (named dist)

Figure 12.7. The general structure of gulp tasks you’ll write for this chapter’s gulpfile

Figure 12.8. The LiveReload extension icon in the Chrome toolbar. Clicking this icon enables the LiveReload listener that receives signals from the local LiveReload server to reload when files change.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset