<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://web.dev/</id>
  <title>Michael DiBlasio on web.dev</title>
  <updated>2026-04-15T23:21:06Z</updated>
  <author>
    <name>Michael DiBlasio</name>
  </author>
  <link href="https://web.dev/authors/mdiblasio/feed.xml" rel="self"/>
  <link href="https://web.dev/"/>
  <icon>https://web-dev.imgix.net/image/admin/CO9R6GSKlH794WHxbpQD.jpg?auto=format</icon>
  <logo>https://web.dev/images/shared/rss-banner.png</logo>
  <subtitle>Our latest news, updates, and stories by Michael DiBlasio.</subtitle>
  
  
  <entry>
    <title>Minify and compress network payloads with brotli</title>
    <link href="https://web.dev/codelab-text-compression-brotli/"/>
    <updated>2019-05-05T00:00:00Z</updated>
    <id>https://web.dev/codelab-text-compression-brotli/</id>
    <content type="html" mode="escaped">&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; This codelab uses Chrome DevTools. &lt;a href=&quot;https://www.google.com/chrome&quot;&gt;Download Chrome&lt;/a&gt; if you don&#39;t already have it. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;This codelab is an extension of the &lt;a href=&quot;https://web.dev/codelab-text-compression&quot;&gt;Minify and compress network payloads
codelab&lt;/a&gt;
and assumes you are familiar with the basics concepts of compression. As
compared to other compression algorithms like &lt;code&gt;gzip&lt;/code&gt;, this codelab explores how
Brotli compression can further reduce compression ratios and your app&#39;s overall
size.&lt;/p&gt;
&lt;img alt=&quot;App screenshot&quot; decoding=&quot;async&quot; height=&quot;535&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/k94QI9lhJ39aXpwUrMNk.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/k94QI9lhJ39aXpwUrMNk.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/k94QI9lhJ39aXpwUrMNk.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/k94QI9lhJ39aXpwUrMNk.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/k94QI9lhJ39aXpwUrMNk.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/k94QI9lhJ39aXpwUrMNk.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/k94QI9lhJ39aXpwUrMNk.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/k94QI9lhJ39aXpwUrMNk.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/k94QI9lhJ39aXpwUrMNk.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/k94QI9lhJ39aXpwUrMNk.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/k94QI9lhJ39aXpwUrMNk.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/k94QI9lhJ39aXpwUrMNk.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/k94QI9lhJ39aXpwUrMNk.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/k94QI9lhJ39aXpwUrMNk.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/k94QI9lhJ39aXpwUrMNk.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/k94QI9lhJ39aXpwUrMNk.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/k94QI9lhJ39aXpwUrMNk.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/k94QI9lhJ39aXpwUrMNk.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;h2 id=&quot;measure&quot;&gt;Measure &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/codelab-text-compression-brotli/#measure&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Since &lt;a href=&quot;https://webpack.js.org/&quot;&gt;webpack&lt;/a&gt; is used in this application, any changes made to the codewill trigger a new build which can take a few seconds. Once it completes, you should see your changes reflectedin the application. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Before diving in to add optimizations, it&#39;s always a good idea to first analyze
the current state of the application.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Remix to Edit&lt;/strong&gt; to make the project editable.&lt;/li&gt;
&lt;li&gt;To preview the site, press &lt;strong&gt;View App&lt;/strong&gt;. Then press
&lt;strong&gt;Fullscreen&lt;/strong&gt;
&lt;img src=&quot;https://web.dev/images/glitch/fullscreen.svg&quot; alt=&quot;fullscreen&quot; style=&quot;padding: 4px 8px; opacity: .5; border: 1px solid #c3c3c3; border-radius: 5px; margin-top: 0;&quot; /&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In the previous &lt;a href=&quot;https://web.dev/codelab-text-compression&quot;&gt;Minify and compress network payloads
codelab&lt;/a&gt;,
we reduced the size of &lt;code&gt;main.js&lt;/code&gt; from 225 KB to 61.6 KB. In this codelab, you
will explore how Brotli compression can reduce this bundle size even further.&lt;/p&gt;
&lt;h2 id=&quot;brotli-compression&quot;&gt;Brotli Compression &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/codelab-text-compression-brotli/#brotli-compression&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;aside class=&quot;aside flow bg-state-warn-bg color-state-warn-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block color-state-warn-text&quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Warning sign&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M23 21L12 2 1 21h22zm-12-3v-2h2v2h-2zm0-4h2v-4h-2v4z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; Many hosting platforms, CDNs and reverse proxy servers either encode assets with compression by default or allow you to easily configure them. If your hosting platform supports Brotli, you may not need to setup your server to compress your assets with Brotli as described in this tutorial. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;&lt;a href=&quot;https://opensource.googleblog.com/2015/09/introducing-brotli-new-compression.html&quot; rel=&quot;noopener&quot;&gt;Brotli&lt;/a&gt;
is a newer compression algorithm which can provide even better text compression
results than &lt;code&gt;gzip&lt;/code&gt;. According to
&lt;a href=&quot;https://certsimple.com/blog/nginx-brotli&quot; rel=&quot;noopener&quot;&gt;CertSimple&lt;/a&gt;, Brotli performance is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;14% smaller than &lt;code&gt;gzip&lt;/code&gt; for JavaScript&lt;/li&gt;
&lt;li&gt;21% smaller than &lt;code&gt;gzip&lt;/code&gt; for HTML&lt;/li&gt;
&lt;li&gt;17% smaller than &lt;code&gt;gzip&lt;/code&gt; for CSS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To use Brotli, your server must support HTTPS. Brotli is supported in the
&lt;a href=&quot;https://caniuse.com/#feat=brotli&quot; rel=&quot;noopener&quot;&gt;latest versions of most browsers&lt;/a&gt;. Browsers
that support Brotli will include &lt;code&gt;br&lt;/code&gt; in &lt;code&gt;Accept-Encoding&lt;/code&gt; headers:&lt;/p&gt;
&lt;pre&gt;
Accept-Encoding: gzip, deflate, &lt;strong&gt;br&lt;/strong&gt;
&lt;/pre&gt;
&lt;p&gt;You can determine which compression algorithm is used via the &lt;code&gt;Content-Encoding&lt;/code&gt;
field in the Chrome Developer Tools Network tab (&lt;code&gt;Command+Option+I&lt;/code&gt; or
&lt;code&gt;Ctrl+Alt+I&lt;/code&gt;):&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Network panel&quot; decoding=&quot;async&quot; height=&quot;136&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/ZddI1FFjEckeO8mabgYl.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/ZddI1FFjEckeO8mabgYl.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/ZddI1FFjEckeO8mabgYl.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/ZddI1FFjEckeO8mabgYl.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/ZddI1FFjEckeO8mabgYl.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/ZddI1FFjEckeO8mabgYl.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/ZddI1FFjEckeO8mabgYl.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/ZddI1FFjEckeO8mabgYl.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/ZddI1FFjEckeO8mabgYl.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/ZddI1FFjEckeO8mabgYl.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/ZddI1FFjEckeO8mabgYl.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/ZddI1FFjEckeO8mabgYl.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/ZddI1FFjEckeO8mabgYl.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/ZddI1FFjEckeO8mabgYl.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/ZddI1FFjEckeO8mabgYl.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/ZddI1FFjEckeO8mabgYl.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/ZddI1FFjEckeO8mabgYl.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/ZddI1FFjEckeO8mabgYl.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;enabling-brotli&quot;&gt;Enabling Brotli &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/codelab-text-compression-brotli/#enabling-brotli&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;dynamic-compression&quot;&gt;Dynamic compression &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/codelab-text-compression-brotli/#dynamic-compression&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Dynamic compression&lt;/strong&gt; involves compressing assets on-the-fly as they get
requested by the browser.&lt;/p&gt;
&lt;h4 id=&quot;pros&quot;&gt;Pros &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/codelab-text-compression-brotli/#pros&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Creating and updating saved compressed versions of assets does not need to be
done.&lt;/li&gt;
&lt;li&gt;Compressing on-the-fly works especially well for web pages that are
dynamically generated.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;cons&quot;&gt;Cons &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/codelab-text-compression-brotli/#cons&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Compressing files at higher levels to achieve better compression ratios takes
longer. This can cause a performance hit as the user waits for assets to
compress before they are sent by the server.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;dynamic-compression-with-nodeexpress&quot;&gt;Dynamic compression with Node/Express &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/codelab-text-compression-brotli/#dynamic-compression-with-nodeexpress&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;server.js&lt;/code&gt; file is responsible for setting up the Node server that hosts
the application.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; express &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;express&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;public&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; listener &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PORT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Your app is listening on port &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; listener&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;All this currently does is import &lt;code&gt;express&lt;/code&gt; and use the &lt;code&gt;express.static&lt;/code&gt;
middleware to load all the static HTML, JS and CSS files in the
&lt;code&gt;public/directory&lt;/code&gt; (and those files are created by webpack with every build).&lt;/p&gt;
&lt;p&gt;To make sure all of the assets are compressed using brotli every time they&#39;re
requested, the &lt;a href=&quot;https://github.com/aickin/shrink-ray#readme&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;shrink-ray&lt;/code&gt;&lt;/a&gt;
module can be used. Begin by adding it as a &lt;code&gt;devDependency&lt;/code&gt; in &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;devDependencies&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token comment&quot;&gt;//...&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;shrink-ray&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;^0.1.3&quot;&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;And import it into the server file, &lt;code&gt;server.js&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; express &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;express&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; shrinkRay &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;shrink-ray&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;And add it as a middleware before &lt;code&gt;express.static&lt;/code&gt; is mounted:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//...&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// compress all requests&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;shrinkRay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;public&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Now reload the app, and take a look at the bundle size in the Network panel:&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Bundle size with dynamic Brotli compression&quot; decoding=&quot;async&quot; height=&quot;97&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 724px) 724px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/KXDWBC6aH4o6MVJvBu8X.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/KXDWBC6aH4o6MVJvBu8X.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/KXDWBC6aH4o6MVJvBu8X.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/KXDWBC6aH4o6MVJvBu8X.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/KXDWBC6aH4o6MVJvBu8X.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/KXDWBC6aH4o6MVJvBu8X.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/KXDWBC6aH4o6MVJvBu8X.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/KXDWBC6aH4o6MVJvBu8X.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/KXDWBC6aH4o6MVJvBu8X.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/KXDWBC6aH4o6MVJvBu8X.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/KXDWBC6aH4o6MVJvBu8X.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/KXDWBC6aH4o6MVJvBu8X.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/KXDWBC6aH4o6MVJvBu8X.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/KXDWBC6aH4o6MVJvBu8X.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/KXDWBC6aH4o6MVJvBu8X.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/KXDWBC6aH4o6MVJvBu8X.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/KXDWBC6aH4o6MVJvBu8X.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/KXDWBC6aH4o6MVJvBu8X.png?auto=format&amp;w=1448 1448w&quot; width=&quot;724&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;You can now see &lt;code&gt;brotli&lt;/code&gt; is applied from &lt;code&gt;bz&lt;/code&gt; in the &lt;code&gt;Content-Encoding&lt;/code&gt; header.
&lt;code&gt;main.bundle.js&lt;/code&gt; is reduced from &lt;strong&gt;225 KB to 53.1 KB&lt;/strong&gt;! This is ~14% smaller
compared to &lt;code&gt;gzip&lt;/code&gt; (61.6 KB).&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Brotli has eleven quality levels  from &lt;code&gt;0&lt;/code&gt; (no compression) to &lt;code&gt;9&lt;/code&gt; (maximum compression). A quality of &lt;code&gt;1&lt;/code&gt; is very fast but less effective, whereas a quality setting of &lt;code&gt;11&lt;/code&gt; is very slow but provides big savings in file size. Note that unlike the standard brotli library, which defaults to quality &lt;code&gt;11&lt;/code&gt;, &lt;code&gt;shrink-ray&lt;/code&gt; defaults to quality &lt;code&gt;4&lt;/code&gt;, which is generally more appropriate for dynamic content. You can adjust the parameters of the brotli algorithm by passing in an &lt;code&gt;options&lt;/code&gt; parameters to &lt;code&gt;shrinkRay([options])&lt;/code&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;static-compression&quot;&gt;Static compression &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/codelab-text-compression-brotli/#static-compression&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The idea behind static compression is to have assets compressed and saved ahead
of time.&lt;/p&gt;
&lt;h4 id=&quot;pros-2&quot;&gt;Pros &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/codelab-text-compression-brotli/#pros-2&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Latency due to high compression levels is not a concern anymore. Nothing
needs to happen on-the-fly to compress files as they can now be fetched
directly.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;cons-2&quot;&gt;Cons &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/codelab-text-compression-brotli/#cons-2&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Assets need to compressed with every build. Build times can increase
significantly if high compression levels are used.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;static-compression-with-nodeexpress-and-webpack&quot;&gt;Static compression with Node/Express and webpack &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/codelab-text-compression-brotli/#static-compression-with-nodeexpress-and-webpack&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Since &lt;strong&gt;static compression&lt;/strong&gt; involves compressing files ahead of time, webpack
settings can be modified to compress assets as part of the build step. The
&lt;code&gt;brotli-webpack-plugin&lt;/code&gt; can be used for this.&lt;/p&gt;
&lt;p&gt;Begin by adding it as a &lt;code&gt;devDependency&lt;/code&gt; in &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token string-property property&quot;&gt;&quot;devDependencies&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token comment&quot;&gt;//...&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;brotli-webpack-plugin&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;^1.1.0&quot;&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Like any other webpack plugin, import it in the configurations file,
&lt;code&gt;webpack.config.js&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;path&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//...&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; BrotliPlugin &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;brotli-webpack-plugin&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/mark&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;And include it within the plugins array:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BrotliPlugin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;asset&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;[file].br&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;&lt;span class=&quot;token special-escape escape&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;token group punctuation&quot;&gt;(&lt;/span&gt;js&lt;span class=&quot;token group punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token anchor function&quot;&gt;$&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The plugin array uses the following arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;asset&lt;/code&gt;: The target asset name.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[file]&lt;/code&gt; is replaced with the original asset file name.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;test&lt;/code&gt;: All assets that match this RegExp (that is, JavaScript assets ending in
&lt;code&gt;.js&lt;/code&gt;) are processed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, &lt;code&gt;main.js&lt;/code&gt; would be renamed to &lt;code&gt;main.js.br&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When the app reloads and rebuilds, a compressed version of the main bundle is
now created. Open the Glitch Console to take a look at what&#39;s inside the final
&lt;code&gt;public/&lt;/code&gt; directory that&#39;s served by the Node server.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Click the &lt;strong&gt;Tools&lt;/strong&gt; button.&lt;/li&gt;
&lt;li&gt;Click the &lt;strong&gt;Console&lt;/strong&gt; button.&lt;/li&gt;
&lt;li&gt;In the console, run the following commands to change into the &lt;code&gt;public&lt;/code&gt;
directory and see all of its files:&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; public&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; -lh&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;figure&gt;
  &lt;img alt=&quot;Bundle size with static Brotli compression&quot; decoding=&quot;async&quot; height=&quot;133&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 489px) 489px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/GOlRrAhdDWO7yi7Bm1Pg.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/GOlRrAhdDWO7yi7Bm1Pg.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/GOlRrAhdDWO7yi7Bm1Pg.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/GOlRrAhdDWO7yi7Bm1Pg.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/GOlRrAhdDWO7yi7Bm1Pg.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/GOlRrAhdDWO7yi7Bm1Pg.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/GOlRrAhdDWO7yi7Bm1Pg.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/GOlRrAhdDWO7yi7Bm1Pg.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/GOlRrAhdDWO7yi7Bm1Pg.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/GOlRrAhdDWO7yi7Bm1Pg.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/GOlRrAhdDWO7yi7Bm1Pg.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/GOlRrAhdDWO7yi7Bm1Pg.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/GOlRrAhdDWO7yi7Bm1Pg.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/GOlRrAhdDWO7yi7Bm1Pg.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/GOlRrAhdDWO7yi7Bm1Pg.png?auto=format&amp;w=978 978w&quot; width=&quot;489&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;The brotli compressed version of the bundle, &lt;code&gt;main.bundle.js.br&lt;/code&gt;, is now saved
here as well and is &lt;strong&gt;~76% smaller in size&lt;/strong&gt; (225 KB vs. 53 KB) than
&lt;code&gt;main.bundle.js&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Next, tell the server to send these brotli-compressed files whenever their
original JS versions are being requested. This can be done by defining a new
route in &lt;code&gt;server.js&lt;/code&gt; before the files are served with &lt;code&gt;express.static&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; express &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;express&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;*.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;.br&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Content-Encoding&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;br&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Content-Type&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;application/javascript; charset=UTF-8&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  &lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;public&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;app.get&lt;/code&gt; is used to tell the server how to respond to a &lt;code&gt;GET&lt;/code&gt; request for a
specific endpoint. A callback function is then used to define how to handle this
request. The route works like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Specifying &lt;code&gt;&#39;*.js&#39;&lt;/code&gt; as the first argument means that this works for every
endpoint that is fired to fetch a JS file.&lt;/li&gt;
&lt;li&gt;Within the callback, &lt;code&gt;.br&lt;/code&gt; is attached to the URL of the request and the
&lt;code&gt;Content-Encoding&lt;/code&gt; response header is set to &lt;code&gt;br&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Content-Type&lt;/code&gt; header is set to &lt;code&gt;application/javascript; charset=UTF-8&lt;/code&gt; to
specify the MIME type.&lt;/li&gt;
&lt;li&gt;Finally, &lt;code&gt;next()&lt;/code&gt; ensures that the sequence continues to any callback that may
be next.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Because some browsers may not support brotli compression, confirm brotli is
supported before returning the brotli-compressed file by checking the
&lt;code&gt;Accept-Encoding&lt;/code&gt; request header includes &lt;code&gt;br&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; express &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;express&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;*.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Accept-Encoding&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;br&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;.br&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Accept-Encoding&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Content-Encoding&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;br&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Content-Type&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;application/javascript; charset=UTF-8&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/mark&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;express&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;public&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Once the app reloads, take a look at the Network panel once more.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Bundle size of 53.1 KB (from 225KB)&quot; decoding=&quot;async&quot; height=&quot;97&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 724px) 724px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/2rJrkqLzWt3MT4XxNsYn.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/2rJrkqLzWt3MT4XxNsYn.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/2rJrkqLzWt3MT4XxNsYn.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/2rJrkqLzWt3MT4XxNsYn.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/2rJrkqLzWt3MT4XxNsYn.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/2rJrkqLzWt3MT4XxNsYn.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/2rJrkqLzWt3MT4XxNsYn.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/2rJrkqLzWt3MT4XxNsYn.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/2rJrkqLzWt3MT4XxNsYn.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/2rJrkqLzWt3MT4XxNsYn.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/2rJrkqLzWt3MT4XxNsYn.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/2rJrkqLzWt3MT4XxNsYn.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/2rJrkqLzWt3MT4XxNsYn.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/2rJrkqLzWt3MT4XxNsYn.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/2rJrkqLzWt3MT4XxNsYn.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/2rJrkqLzWt3MT4XxNsYn.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/2rJrkqLzWt3MT4XxNsYn.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/2rJrkqLzWt3MT4XxNsYn.png?auto=format&amp;w=1448 1448w&quot; width=&quot;724&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Success! You have used Brotli compression to further compress your assets!&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/codelab-text-compression-brotli/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This codelab illustrated how &lt;code&gt;brotli&lt;/code&gt; can further reduce your app&#39;s overall
size. Where supported, &lt;code&gt;brotli&lt;/code&gt; is a more powerful compression algorithm than
&lt;code&gt;gzip&lt;/code&gt;.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-warn-bg color-state-warn-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block color-state-warn-text&quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Warning sign&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M23 21L12 2 1 21h22zm-12-3v-2h2v2h-2zm0-4h2v-4h-2v4z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; Remember to check if your CDN supports &lt;code&gt;brotli&lt;/code&gt; before manually implementing. If you need to implement &lt;code&gt;brotli&lt;/code&gt; manually (as described in this codelab) but have CDN support for other compression algorithms such as &lt;code&gt;gzip&lt;/code&gt;, it is a good idea to weigh the benefits of &lt;code&gt;brotli&lt;/code&gt; against the effort required to implement. &lt;/div&gt;&lt;/aside&gt;
</content>
    <author>
      <name>Michael DiBlasio</name>
    </author>
  </entry>
</feed>
