From 97cb0c2644d8056065b48cf508dd636d9b65a8e6 Mon Sep 17 00:00:00 2001 From: Rick Viscomi Date: Sat, 24 Sep 2022 15:15:00 -0400 Subject: [PATCH] 2022 JavaScript chapter (#3137) * initial md conversion with figure placeholders * figures * figure screenshots * Optimised images with calibre/image-actions * enable js chapter * edits * linter * retake screenshots * Optimised images with calibre/image-actions * linter * removed unedited flag * Retake images * add Barry to reviewers * Apply suggestions from code review Co-authored-by: Barry Pollard * 3P figure * Apply suggestions from code review Co-authored-by: Barry Pollard * figure descriptions, regenerated some screenshots * Optimised images with calibre/image-actions * malchata bio * Retake images * Intl links * Update src/content/en/2022/javascript.md * Update src/content/en/2022/javascript.md Co-authored-by: Jeremy Wagner * Apply suggestions from code review Co-authored-by: Minko Gechev * Add featured quotes and stats * Remove over use of emphasis * Fix async/defer stats Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Barry Pollard Co-authored-by: Jeremy Wagner Co-authored-by: Minko Gechev --- src/config/2022.json | 3 +- src/content/en/2022/javascript.md | 1074 ++++++++++++++++- .../images/2022/javascript/babel-rank.png | Bin 0 -> 22466 bytes .../images/2022/javascript/bytes-party.png | Bin 0 -> 20981 bytes .../images/2022/javascript/bytes-per-page.png | Bin 0 -> 20515 bytes .../2022/javascript/compression-by-host.png | Bin 0 -> 22683 bytes .../2022/javascript/compression-methods.png | Bin 0 -> 25102 bytes src/static/images/2022/javascript/fid.png | Bin 0 -> 17717 bytes .../2022/javascript/frameworks-libraries.png | Bin 0 -> 40431 bytes .../2022/javascript/injected-scripts.png | Bin 0 -> 21553 bytes src/static/images/2022/javascript/inp.png | Bin 0 -> 22234 bytes .../javascript/lighthouse-unminified-avg.png | Bin 0 -> 19398 bytes .../lighthouse-unminified-bytes.png | Bin 0 -> 18783 bytes .../2022/javascript/lighthouse-unminified.png | Bin 0 -> 24012 bytes .../2022/javascript/long-tasks-time.png | Bin 0 -> 22734 bytes .../images/2022/javascript/long-tasks.png | Bin 0 -> 20222 bytes .../images/2022/javascript/modulepreload.png | Bin 0 -> 21406 bytes .../images/2022/javascript/parcel-rank.png | Bin 0 -> 22585 bytes .../images/2022/javascript/prefetch.png | Bin 0 -> 21441 bytes src/static/images/2022/javascript/preload.png | Bin 0 -> 20498 bytes .../render-blocking-scripts-rank.png | Bin 0 -> 22151 bytes .../images/2022/javascript/requests-party.png | Bin 0 -> 20348 bytes .../2022/javascript/requests-per-page.png | Bin 0 -> 20403 bytes src/static/images/2022/javascript/tbt.png | Bin 0 -> 17660 bytes src/static/images/2022/javascript/tti.png | Bin 0 -> 16275 bytes .../images/2022/javascript/uncompressed.png | Bin 0 -> 21105 bytes .../images/2022/javascript/unused-js.png | Bin 0 -> 21241 bytes .../images/2022/javascript/webpack-rank.png | Bin 0 -> 22493 bytes 28 files changed, 1064 insertions(+), 13 deletions(-) create mode 100644 src/static/images/2022/javascript/babel-rank.png create mode 100644 src/static/images/2022/javascript/bytes-party.png create mode 100644 src/static/images/2022/javascript/bytes-per-page.png create mode 100644 src/static/images/2022/javascript/compression-by-host.png create mode 100644 src/static/images/2022/javascript/compression-methods.png create mode 100644 src/static/images/2022/javascript/fid.png create mode 100644 src/static/images/2022/javascript/frameworks-libraries.png create mode 100644 src/static/images/2022/javascript/injected-scripts.png create mode 100644 src/static/images/2022/javascript/inp.png create mode 100644 src/static/images/2022/javascript/lighthouse-unminified-avg.png create mode 100644 src/static/images/2022/javascript/lighthouse-unminified-bytes.png create mode 100644 src/static/images/2022/javascript/lighthouse-unminified.png create mode 100644 src/static/images/2022/javascript/long-tasks-time.png create mode 100644 src/static/images/2022/javascript/long-tasks.png create mode 100644 src/static/images/2022/javascript/modulepreload.png create mode 100644 src/static/images/2022/javascript/parcel-rank.png create mode 100644 src/static/images/2022/javascript/prefetch.png create mode 100644 src/static/images/2022/javascript/preload.png create mode 100644 src/static/images/2022/javascript/render-blocking-scripts-rank.png create mode 100644 src/static/images/2022/javascript/requests-party.png create mode 100644 src/static/images/2022/javascript/requests-per-page.png create mode 100644 src/static/images/2022/javascript/tbt.png create mode 100644 src/static/images/2022/javascript/tti.png create mode 100644 src/static/images/2022/javascript/uncompressed.png create mode 100644 src/static/images/2022/javascript/unused-js.png create mode 100644 src/static/images/2022/javascript/webpack-rank.png diff --git a/src/config/2022.json b/src/config/2022.json index 3d61854d17c..4072140e68b 100644 --- a/src/config/2022.json +++ b/src/config/2022.json @@ -22,8 +22,7 @@ "part": "I", "chapter_number": "2", "title": "JavaScript", - "slug": "javascript", - "todo": true + "slug": "javascript" }, { "part": "I", diff --git a/src/content/en/2022/javascript.md b/src/content/en/2022/javascript.md index 57736bd3fd4..061af1cadba 100644 --- a/src/content/en/2022/javascript.md +++ b/src/content/en/2022/javascript.md @@ -4,19 +4,1071 @@ title: JavaScript #TODO - Review and update chapter description description: JavaScript chapter of the 2022 Web Almanac covering the usage of JavaScript on the web, libraries and frameworks, compression, web components, and source maps. authors: [malchata, ibnesayeed] -reviewers: [mgechev, pankajparkar, NishuGoel, seldo, housseindjirdeh, kevinfarrugia] +reviewers: [mgechev, pankajparkar, NishuGoel, seldo, housseindjirdeh, kevinfarrugia, tunetheweb] analysts: [NishuGoel, kevinfarrugia] -editors: [DesignrKnight] +editors: [DesignrKnight, rviscomi] translators: [] +malchata_bio: Jeremy Wagner is a technical writer for Google on performance and Core Web Vitals. He has also written for A List Apart, CSS-Tricks, and Smashing Magazine. Jeremy will someday relocate to the remote wilderness where sand has not yet been taught to think. Until then, he continues to reside in Minnesota’s Twin Cities with his wife and stepdaughters, bemoaning the existence of strip malls. results: https://docs.google.com/spreadsheets/d/1vOeFUyfEtWRen3Xj57ZsWav40n5tlcJoV0HmAxmNE_I/ -featured_quote: TODO -featured_stat_1: TODO -featured_stat_label_1: TODO -featured_stat_2: TODO -featured_stat_label_2: TODO -featured_stat_3: TODO -featured_stat_label_3: TODO -unedited: true +featured_quote: The state of JavaScript is a constantly evolving phenomenon. It's clear that we have an increased reliance on it more than ever, but that spells trouble for the collective user experience of the web. We need to do all we can—and more—to stem the tide of how much JavaScript we ship on production websites. +featured_stat_1: 26% +featured_stat_label_1: Top million pages that transform code with Babel +featured_stat_2: 8% +featured_stat_label_2: Extra JavaScript downloaded in last year on mobile +featured_stat_3: 20 +featured_stat_label_3: Median third-party scripts shipped --- -## TODO +## Introduction + +JavaScript is a powerful force that provides the lion's share of interactivity on the web. It drives behaviors from the simple to the complex, and is making more things possible on the web than ever before. + +Yet, the increased usage of JavaScript to deliver rich user experiences comes at a cost. From the moment JavaScript is downloaded, parsed, and compiled, to every line of code it executes, the browser must orchestrate all kinds of work to make everything possible. Doing too little with JavaScript means you might fall short of fulfilling user experience and business goals. On the other hand, shipping too much on JavaScript means you will be creating user experiences that are slow to load, sluggish to respond, and frustrating to users. + +This year, we'll once again be looking at the role of JavaScript on the web, as we present our findings for 2022 and offering advice for creating delightful user experiences. + +## How much JavaScript do we load? + +To begin, we'll assess the amount of JavaScript web developers ship on the web. After all, before improvements can be made, an assessment of the current landscape must be performed. + +{{ figure_markup( + image="bytes-per-page.png", + caption="Distribution of the amount of JavaScript loaded per page.", + description="Bar chart showing the 10, 25, 50, 75, and 90th percentiles of JavaScript kilobytes per page. On mobile pages, the values are 87, 209, 461, 857, and 1,367 KB respectively. Desktop values are slightly higher across the board. ", + chart_url="https://docs.google.com/spreadsheets/d/e/2PACX-1vTok8UGqYaA58uKaASB2pfM2jlmQu6g3kwHxB6Lb8L7dbccyDtQht823YhchdXRG8SZpB3asRayJI97/pubchart?oid=807278764&format=interactive", + sheets_gid="1117050794", + sql_file="bytes_2022.sql" + ) +}} + +As was the case last year, this year marks yet another increase in the amount of JavaScript shipped to browsers. [From 2021](../2021/javascript#how-much-javascript-do-we-load) to 2022, an increase of 8% for mobile devices was observed, whereas desktop devices saw an increase of 10%. While this increase is less steep than in previous years, it's nonetheless the continuation of a concerning trend. While device capabilities continue to improve, not every one is running the latest device. The fact remains that more JavaScript equates to more strain on a device's resources. + +{{ figure_markup( + image="unused-js.png", + caption="Distribution of the amount of unused JavaScript bytes.", + description="Bar chart showing the 10, 25, 50, 75, and 90th percentiles of kilobytes of unused JavaScript per page. On mobile pages, the values are 0, 62, 162, 342, and 604. Desktop trends slightly higher.", + chart_url="https://docs.google.com/spreadsheets/d/e/2PACX-1vTok8UGqYaA58uKaASB2pfM2jlmQu6g3kwHxB6Lb8L7dbccyDtQht823YhchdXRG8SZpB3asRayJI97/pubchart?oid=1640758017&format=interactive", + sheets_gid="943216000", + sql_file="unused_js_bytes_distribution.sql" + ) +}} + +According to Lighthouse, the median mobile page loads 162 KB of unused JavaScript. At the 90th percentile, 604 KB of JavaScript are unused. This is a slight uptick from last year, where the median and 90th percentile of unused JavaScript was 155 KB and 598 KB, respectively. All of this represents a very large amount of unused JavaScript, especially when you consider that this analysis tracks the transfer size of JavaScript resources which, if compressed, means that the decompressed portion of used JavaScript may be a lot larger than the chart suggests. + +When contrasted with the total number of bytes loaded for mobile pages at the median, unused JavaScript accounts for 35% of all loaded scripts. This is down slightly from last year's figure of 36%, but is still a significantly large chunk of bytes loaded that go unused. This suggests that many pages are loading scripts that may not be used on the current page, or are triggered by interactions later on in the page lifecycle, and may benefit from [dynamic `import()`](#dynamic-import) to reduce startup costs. + +## JavaScript requests per page + +Every resource on a page will kick off at least one request, and possibly more if a resource makes additional requests for more resources. + +Where script requests are concerned, the more there are, the more likely you'll not just load more JavaScript, but also increase contention between script resources that may bog down the main thread, leading to slower startup. + +{{ figure_markup( + image="requests-per-page.png", + caption="Distribution of the number of JavaScript requests per page.", + description="Bar chart showing the 10, 25, 50, 75, and 90th percentiles of JavaScript requests per page. On mobile pages, the values are 4, 10, 21, 37, and 60. Desktop trends slightly higher by 1-3 requests across the board.", + chart_url="https://docs.google.com/spreadsheets/d/e/2PACX-1vTok8UGqYaA58uKaASB2pfM2jlmQu6g3kwHxB6Lb8L7dbccyDtQht823YhchdXRG8SZpB3asRayJI97/pubchart?oid=372493183&format=interactive", + sheets_gid="1148191446", + sql_file="requests_2022.sql" + ) +}} + +In 2022, the median mobile page responded to 21 JavaScript requests, whereas at the 90th percentile, there were 60. Compared to last year, this is an increase of 1 request at the median and 4 requests at the 90th percentile. + +Where desktop devices in 2022 are concerned, there are 22 JavaScript requests at the median, and 63 at the 90th percentile. Compared to last year, this is an increase of 1 JavaScript request at the median, and 4 at the 90th percentile—the same increase as noted for mobile devices. + +While not a large increase in the number of requests, it does continue the trend of increased requests year over year since the Web Almanac's inception in 2019. + +## How is JavaScript processed? + +Since the advent of JavaScript runtimes such as Node.js, it has become increasingly common to rely on build tools in order to bundle and transform JavaScript. These tools, while undeniably useful, can have effects on how much JavaScript is shipped. New to the Web Almanac this year, we're presenting data on the usage of bundlers and transpilers. + +### Bundlers + +JavaScript bundlers are build-time tools that process a project's JavaScript source code and then apply transformations and optimizations to it. The output is production-ready JavaScript. Take the following code as an example: + +```js +function sum (a, b) { + return a + b; +} +``` + +A bundler will transform this code to a smaller, but more optimized equivalent that takes less time for the browser to download: + +```js +function n(n,r){return n+r} +``` + +Given the optimizations bundlers perform, they are a crucial part of optimizing source code for better performance in production environments. + +There are a wealth of choices when it comes to JavaScript bundlers, but one that pops into mind often is webpack. Fortunately, webpack's generated JavaScript contains a number of signatures (`webpackJsonp`, for example) that make it possible to detect if a website's production JavaScript has been bundled using webpack. + +{{ figure_markup( + image="webpack-rank.png", + caption="Pages that use webpack-bundled JavaScript by rank.", + description="Bar chart showing the percentage of pages that use webpack, in decreasing order of popularity. On mobile, the values are 17% for the top 1k, 15% for the top 10k, 12% for the top 100k, 8% for the top 1M, and 5% over all websites. Desktop pages trend close to mobile.", + chart_url="https://docs.google.com/spreadsheets/d/e/2PACX-1vTok8UGqYaA58uKaASB2pfM2jlmQu6g3kwHxB6Lb8L7dbccyDtQht823YhchdXRG8SZpB3asRayJI97/pubchart?oid=1191436570&format=interactive", + sheets_gid="1329160999", + sql_file="usage_of_webpack_by_rank.sql" + ) +}} + +Of the 1,000 most popular websites, 17% use webpack as a bundler. This makes sense, as many of the top pages HTTP Archive crawls are likely to be high-profile ecommerce sites that use webpack to bundle and optimize source code. Even so, the fact that 5% of the all pages in the HTTP Archive dataset use webpack is a significant statistic. However, webpack isn't the only bundler in use. + +{{ figure_markup( + image="parcel-rank.png", + caption="Pages that use Parcel-bundled JavaScript by rank.", + description="Bar chart showing the percentage of pages that use Parcel, in decreasing order of popularity. On mobile, the values are 1.3% for the top 1k, 1.9% for the top 10k, 1.5% for the top 100k, 1.2% for the top 1M, and 1.3% over all websites. Desktop pages trend close to mobile.", + chart_url="https://docs.google.com/spreadsheets/d/e/2PACX-1vTok8UGqYaA58uKaASB2pfM2jlmQu6g3kwHxB6Lb8L7dbccyDtQht823YhchdXRG8SZpB3asRayJI97/pubchart?oid=369910383&format=interactive", + sheets_gid="908384281", + sql_file="usage_of_parcel_by_rank.sql" + ) +}} + +Parcel is a noteworthy alternative to webpack, and its adoption is significant. Parcel's adoption is consistent across all ranks, accounting for a range of 1.2% to 1.9% across rankings. + +While HTTP Archive is unable to track the usage of all bundlers in the ecosystem, bundler usage is significant in the overall picture of JavaScript in that they're not only important to the developer experience, but the overhead they can contribute in the form of dependency management code can be a factor in how much JavaScript is shipped. It's worth checking how your overall project settings are configured to produce the most efficient possible output for the browsers your users use. + +### Transpilers + +Transpilers are often used in toolchains at build-time to transform newer JavaScript features into a syntax that can be run in older browsers. Because JavaScript has evolved rapidly over the years, these tools are still in use. New to this year's Web Almanac is an analysis of the usage of Babel in delivering widely compatible, production-ready JavaScript. The singular focus on Babel specifically is due to its wide usage in the developer community over alternatives. + +{{ figure_markup( + image="babel-rank.png", + caption="Pages that use Babel by rank.", + description="Bar chart showing the percentage of pages that use Babel, in decreasing order of popularity. On mobile pages, the values are 40% of the top 1k, 40% of the top 10k, 32% fo the top 100k, 23% of the top 1M, and 26% over all websites. Desktop pages trend close to mobile.", + chart_url="https://docs.google.com/spreadsheets/d/e/2PACX-1vTok8UGqYaA58uKaASB2pfM2jlmQu6g3kwHxB6Lb8L7dbccyDtQht823YhchdXRG8SZpB3asRayJI97/pubchart?oid=1109529452&format=interactive", + sheets_gid="304021769", + sql_file="usage_of_typescript_and_babel_by_rank.sql" + ) +}} + +These results are not a surprising development when you consider how much JavaScript has evolved over the years. In order to maintain broad compatibility for a certain set of browsers, Babel uses transforms to output compatible JavaScript code. + +Transforms are often larger than their untransformed counterparts. When transforms are extensive or duplicated across a codebase, potentially unnecessary or even unused JavaScript may be shipped to users. This can adversely affect performance. + +Considering that even 26% of pages ranked in the top million are transforming their JavaScript source code using Babel, it's not unreasonable to assume that some of these experiences may be shipping transforms they don't need. If you use Babel in your projects, carefully review Babel's available configuration options and plugins to find opportunities to optimize its output. + +Since Babel also relies on Browserslist to figure out whether it needs to transform certain features to a legacy syntax, be sure to also review your Browerslist configuration to ensure that your code is transformed to work in the browsers your users actually use. + +## How is JavaScript requested? + +The manner in which JavaScript is requested may also have performance implications. There are optimal ways you can request JavaScript, and in some cases, there are far less optimal methods. Here, we'll see how the web is shipping JavaScript overall, and how that aligns with performance expectations. + +### `async`, `defer`, `module`, and `nomodule` + +The `async` and `defer` attributes on the HTML `