<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://web.dev/</id>
  <title>Minko Gechev on web.dev</title>
  <updated>2026-04-15T23:21:06Z</updated>
  <author>
    <name>Minko Gechev</name>
  </author>
  <link href="https://web.dev/authors/mgechev/feed.xml" rel="self"/>
  <link href="https://web.dev/"/>
  <icon>https://web-dev.imgix.net/image/admin/OPpZ9x8KCVcxvqgdWXM5.jpg?auto=format</icon>
  <logo>https://web.dev/images/shared/rss-banner.png</logo>
  <subtitle>Our latest news, updates, and stories by Minko Gechev.</subtitle>
  
  
  <entry>
    <title>How CommonJS is making your bundles larger</title>
    <link href="https://web.dev/commonjs-larger-bundles/"/>
    <updated>2020-05-08T00:00:00Z</updated>
    <id>https://web.dev/commonjs-larger-bundles/</id>
    <content type="html" mode="escaped">&lt;p&gt;In this post, we&#39;ll look into what CommonJS is and why it&#39;s making your JavaScript bundles larger than necessary.&lt;/p&gt;
&lt;p&gt;Summary: &lt;strong&gt;To ensure the bundler can successfully optimize your application, avoid depending on CommonJS modules, and use ECMAScript module syntax in your entire application.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;whats-commonjs&quot;&gt;What&#39;s CommonJS? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/commonjs-larger-bundles/#whats-commonjs&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;CommonJS is a standard from 2009 that established conventions for JavaScript modules. It was initially intended for use outside of the web browser, primarily for server-side applications.&lt;/p&gt;
&lt;p&gt;With CommonJS you can define modules, export functionality from them, and import them in other modules. For example, the snippet below defines a module which exports five functions: &lt;code&gt;add&lt;/code&gt;, &lt;code&gt;subtract&lt;/code&gt;, &lt;code&gt;multiply&lt;/code&gt;, &lt;code&gt;divide&lt;/code&gt;, and &lt;code&gt;max&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// utils.js&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; maxBy &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &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;lodash-es&#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;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fns &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function-variable function&quot;&gt;add&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 class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function-variable function&quot;&gt;subtract&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 class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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; a &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function-variable function&quot;&gt;multiply&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 class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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; a &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function-variable function&quot;&gt;divide&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 class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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; a &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function-variable function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;arr&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;maxBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;arr&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;br /&gt;&lt;br /&gt;Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fns&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;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;fnName&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;fnName&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fns&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;fnName&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;Later on, another module can import and use some or all of these functions:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// index.js&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; add &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &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;./utils.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;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 function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Invoking &lt;code&gt;index.js&lt;/code&gt; with &lt;code&gt;node&lt;/code&gt; will output the number &lt;code&gt;3&lt;/code&gt; in the console.&lt;/p&gt;
&lt;p&gt;Because of the lack of a standardized module system in the browser in the early 2010s, CommonJS became a popular module format for JavaScript client-side libraries as well.&lt;/p&gt;
&lt;h2 id=&quot;how-does-commonjs-affect-your-final-bundle-size&quot;&gt;How does CommonJS affect your final bundle size? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/commonjs-larger-bundles/#how-does-commonjs-affect-your-final-bundle-size&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The size of your server-side JavaScript application is not as critical as in the browser, that&#39;s why CommonJS was not designed with reducing the production bundle size in mind. At the same time, &lt;a href=&quot;https://v8.dev/blog/cost-of-javascript-2019&quot; rel=&quot;noopener&quot;&gt;analysis&lt;/a&gt; shows that the JavaScript bundle size is still the number one reason for making browser apps slower.&lt;/p&gt;
&lt;p&gt;JavaScript bundlers and minifiers, such as &lt;code&gt;webpack&lt;/code&gt; and &lt;code&gt;terser&lt;/code&gt;, perform different optimizations to reduce the size of your app. Analyzing your application at build time, they try to remove as much as possible from the source code you&#39;re not using.&lt;/p&gt;
&lt;p&gt;For example, in the snippet above, your final bundle should only include the &lt;code&gt;add&lt;/code&gt; function since this is the only symbol from &lt;code&gt;utils.js&lt;/code&gt; that you import in &lt;code&gt;index.js&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let&#39;s build the app using the following &lt;code&gt;webpack&lt;/code&gt; configuration:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&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;&#39;path&#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;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;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;index.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;output&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;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;out.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__dirname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;dist&#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;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 literal-property property&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;production&#39;&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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Here we specify that we want to use production mode optimizations and use &lt;code&gt;index.js&lt;/code&gt; as an entry point. After invoking &lt;code&gt;webpack&lt;/code&gt;, if we  explore the &lt;a href=&quot;https://github.com/mgechev/commonjs-example/blob/master/commonjs/dist/out.js&quot; rel=&quot;noopener&quot;&gt;output&lt;/a&gt; size, we&#39;ll see something like this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;$ &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; dist &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; -lah&lt;br /&gt;625K Apr &lt;span class=&quot;token number&quot;&gt;13&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;13&lt;/span&gt;:04 out.js&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Notice that &lt;strong&gt;the bundle is 625KB&lt;/strong&gt;. If we look into the output, we&#39;ll find all the functions from &lt;code&gt;utils.js&lt;/code&gt; plus a lot of modules from &lt;a href=&quot;https://lodash.com/&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;lodash&lt;/code&gt;&lt;/a&gt;&lt;strong&gt;. Although we do not use &lt;code&gt;lodash&lt;/code&gt; in &lt;code&gt;index.js&lt;/code&gt; it&#39;s part of the output&lt;/strong&gt;, which adds a lot of extra weight to our production assets.&lt;/p&gt;
&lt;p&gt;Now let us change the module format to &lt;a href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/import&quot; rel=&quot;noopener&quot;&gt;ECMAScript modules&lt;/a&gt; and try again. This time, &lt;code&gt;utils.js&lt;/code&gt; would look like this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&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 class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;subtract&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 class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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; a &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;multiply&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 class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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; a &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;divide&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 class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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; a &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; b&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;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; maxBy &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;lodash-es&#39;&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;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;max&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;arr&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;maxBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;arr&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;And &lt;code&gt;index.js&lt;/code&gt; would import from &lt;code&gt;utils.js&lt;/code&gt; using ECMAScript module syntax:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; add &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;./utils.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&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 function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Using the same &lt;code&gt;webpack&lt;/code&gt; configuration, we can build our application and open the output file. &lt;strong&gt;It is now 40 bytes&lt;/strong&gt; with the following &lt;a href=&quot;https://github.com/mgechev/commonjs-example/blob/master/esm/dist/out.js&quot; rel=&quot;noopener&quot;&gt;output&lt;/a&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&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 class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;use strict&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&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 number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&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;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;Notice that the final bundle does not contain any of the functions from &lt;code&gt;utils.js&lt;/code&gt; that we don&#39;t use, and there&#39;s no trace from &lt;code&gt;lodash&lt;/code&gt;! Even further, &lt;code&gt;terser&lt;/code&gt; (the JavaScript minifier that &lt;code&gt;webpack&lt;/code&gt; uses) inlined the &lt;code&gt;add&lt;/code&gt; function in &lt;code&gt;console.log&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A fair question you might ask is, &lt;strong&gt;why does using CommonJS cause the output bundle to be almost 16,000 times bigger&lt;/strong&gt;? Of course, this is a toy example, in reality, the size difference might not be that large, but the chances are that CommonJS adds significant weight to your production build.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CommonJS modules are harder to optimize in the general case because they are much more dynamic than ES modules. To ensure your bundler and minifier can successfully optimize your application, avoid depending on CommonJS modules, and use ECMAScript module syntax in your entire application.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Notice that even if you&#39;re using ECMAScript modules in &lt;code&gt;index.js&lt;/code&gt;, if the module you&#39;re consuming is a CommonJS module, your app&#39;s bundle size will suffer.&lt;/p&gt;
&lt;h2 id=&quot;why-does-commonjs-make-your-app-larger&quot;&gt;Why does CommonJS make your app larger? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/commonjs-larger-bundles/#why-does-commonjs-make-your-app-larger&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To answer this question, we&#39;ll look at the behavior of the &lt;code&gt;ModuleConcatenationPlugin&lt;/code&gt; in &lt;code&gt;webpack&lt;/code&gt; and, after that, discuss static analyzability. This plugin concatenates the scope of all your modules into one closure and allows for your code to have a faster execution time in the browser. Let&#39;s look at an example:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// utils.js&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&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 class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;subtract&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 class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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; a &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// index.js&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; add &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;./utils.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;subtract&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 class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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; a &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&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 function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Above, we have an ECMAScript module, which we import in &lt;code&gt;index.js&lt;/code&gt;. We also define a &lt;code&gt;subtract&lt;/code&gt; function. We can build the project using the same &lt;code&gt;webpack&lt;/code&gt; configuration as above, but this time, we&#39;ll disable minimization:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&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;&#39;path&#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;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;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;index.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;output&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;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;out.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__dirname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;dist&#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;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 literal-property property&quot;&gt;optimization&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;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;minimize&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&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;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;production&#39;&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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Let us look at the produced output:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&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;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// webpackBootstrap&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;/******/&lt;/span&gt; 	&lt;span class=&quot;token string&quot;&gt;&quot;use strict&quot;&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 comment&quot;&gt;// CONCATENATED MODULE: ./utils.js**&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&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 class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;subtract&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 class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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; a &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// CONCATENATED MODULE: ./index.js**&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;index_subtract&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 class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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; a &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token operator&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 function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&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 operator&quot;&gt;**&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&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;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;In the output above, all the functions are inside the same namespace. To prevent collisions, webpack renamed the &lt;code&gt;subtract&lt;/code&gt; function in &lt;code&gt;index.js&lt;/code&gt; to &lt;code&gt;index_subtract&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If a minifier processes the source code above, it will:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Remove the unused functions &lt;code&gt;subtract&lt;/code&gt; and &lt;code&gt;index_subtract&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Remove all the comments and redundant whitespace&lt;/li&gt;
&lt;li&gt;Inline the body of the &lt;code&gt;add&lt;/code&gt; function in the &lt;code&gt;console.log&lt;/code&gt; call&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Often developers refer to this &lt;strong&gt;removal of unused imports as tree-shaking&lt;/strong&gt;. Tree-shaking was only possible because webpack was able to statically (at build time) understand which symbols we are importing from &lt;code&gt;utils.js&lt;/code&gt; and what symbols it exports.&lt;/p&gt;
&lt;p&gt;This behavior is enabled by default for &lt;strong&gt;ES modules&lt;/strong&gt; because they &lt;strong&gt;are more statically analyzable&lt;/strong&gt;, compared to CommonJS.&lt;/p&gt;
&lt;p&gt;Let us look at the exact same example, but this time change &lt;code&gt;utils.js&lt;/code&gt; to use CommonJS instead of ES modules:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// utils.js&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; maxBy &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &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;lodash-es&#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;const&lt;/span&gt; fns &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function-variable function&quot;&gt;add&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 class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function-variable function&quot;&gt;subtract&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 class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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; a &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function-variable function&quot;&gt;multiply&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 class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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; a &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function-variable function&quot;&gt;divide&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 class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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; a &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function-variable function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;arr&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;maxBy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;arr&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;br /&gt;&lt;br /&gt;Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fns&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;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;fnName&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;fnName&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fns&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;fnName&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;This small update will significantly change the output. Since it&#39;s too long to embed on this page, I&#39;ve shared only a small portion of it:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&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;span class=&quot;token operator&quot;&gt;=&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 string&quot;&gt;&quot;use strict&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;/* harmony import */&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; _utils__WEBPACK_IMPORTED_MODULE_0__ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__webpack_require__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;288&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;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;subtract&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 class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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; a &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; b&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 punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;_utils__WEBPACK_IMPORTED_MODULE_0__&lt;span class=&quot;token comment&quot;&gt;/* .add */&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;IH&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 number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&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 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;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Notice that the final bundle contains some &lt;code&gt;webpack&lt;/code&gt; &amp;quot;runtime&amp;quot;: injected code that is responsible for importing/exporting functionality from the bundled modules. This time, instead of placing all the symbols from &lt;code&gt;utils.js&lt;/code&gt; and &lt;code&gt;index.js&lt;/code&gt; under the same namespace, we require dynamically, at runtime, the &lt;code&gt;add&lt;/code&gt; function using &lt;code&gt;__webpack_require__&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is necessary because with CommonJS we can get the export name from an arbitrary expression. For example, the code below is an absolutely valid construct:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;localStorage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getItem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;random&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;span class=&quot;token operator&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 operator&quot;&gt;=&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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;There&#39;s no way for the bundler to know at build-time what the name of the exported symbol is since this requires information that&#39;s only available at runtime, in the context of the user&#39;s browser.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This way, the minifier is incapable of understanding what exactly &lt;code&gt;index.js&lt;/code&gt; uses from its dependencies so it can&#39;t tree-shake it away.&lt;/strong&gt; We&#39;ll observe the exact same behavior for third-party modules as well. &lt;strong&gt;If we import a CommonJS module from &lt;code&gt;node_modules&lt;/code&gt;, your build toolchain will not be able to optimize it properly.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;tree-shaking-with-commonjs&quot;&gt;Tree-shaking with CommonJS &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/commonjs-larger-bundles/#tree-shaking-with-commonjs&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It&#39;s much harder to analyze CommonJS modules since they are dynamic by definition. For example, the import location in ES modules is always a string literal, compared to CommonJS, where it is an expression.&lt;/p&gt;
&lt;p&gt;In some cases, if the library you&#39;re using follows specific conventions on how it uses CommonJS, it&#39;s possible to remove unused exports at build time using a third-party &lt;code&gt;webpack&lt;/code&gt; &lt;a href=&quot;https://github.com/indutny/webpack-common-shake&quot; rel=&quot;noopener&quot;&gt;plugin&lt;/a&gt;. Although this plugin adds support for tree-shaking, it does not cover all the different ways your dependencies could use CommonJS. This means that you&#39;re not getting the same guarantees as with ES modules. Additionally, it adds an extra cost as part of your build process on top of the default &lt;code&gt;webpack&lt;/code&gt; behavior.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/commonjs-larger-bundles/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;To ensure the bundler can successfully optimize your application, avoid depending on CommonJS modules, and use ECMAScript module syntax in your entire application.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here are a few actionable tips to verify you&#39;re on the optimal path:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use Rollup.js&#39;s &lt;a href=&quot;https://github.com/rollup/plugins/tree/master/packages/node-resolve&quot; rel=&quot;noopener&quot;&gt;node-resolve&lt;/a&gt;
plugin and set the &lt;code&gt;modulesOnly&lt;/code&gt; flag to specify that you want to depend only on ECMAScript modules.&lt;/li&gt;
&lt;li&gt;Use the package &lt;a href=&quot;https://github.com/mgechev/is-esm&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;is-esm&lt;/code&gt;&lt;/a&gt;
to verify that an npm package uses ECMAScript modules.&lt;/li&gt;
&lt;li&gt;If you&#39;re using Angular, by default you&#39;ll get a warning if you depend on non-tree-shakeable modules.&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Minko Gechev</name>
    </author>
  </entry>
  
  <entry>
    <title>Create a Progressive Web App with the Angular CLI</title>
    <link href="https://web.dev/creating-pwa-with-angular-cli/"/>
    <updated>2019-08-15T00:00:00Z</updated>
    <id>https://web.dev/creating-pwa-with-angular-cli/</id>
    <content type="html" mode="escaped">&lt;p&gt;In this post, you&#39;ll learn how to use the Angular command line interface (CLI) to make a &lt;a href=&quot;https://web.dev/discover-installable&quot;&gt;Progressive Web App (PWA)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can find the code sample from this guide &lt;a href=&quot;https://github.com/mgechev/manifest-web-dev&quot; rel=&quot;noopener&quot;&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&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;  This post assumes you&#39;re already familiar with PWAs and their benefits. If you need a refresher, check out the &lt;a href=&quot;https://web.dev/installable&quot;&gt;Installable&lt;/a&gt; collection.  &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;create-an-installable-pwa&quot;&gt;Create an installable PWA &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/creating-pwa-with-angular-cli/#create-an-installable-pwa&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To make your Angular application a PWA, all you need to do is run a single command:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;ng &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; @angular/pwa&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This command will:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a &lt;a href=&quot;https://web.dev/precaching-with-the-angular-service-worker&quot;&gt;service worker&lt;/a&gt; with a default caching configuration.&lt;/li&gt;
&lt;li&gt;Create a &lt;a href=&quot;https://web.dev/add-manifest&quot;&gt;manifest file&lt;/a&gt;, which tells the browser how your app should behave when installed on the user&#39;s device.&lt;/li&gt;
&lt;li&gt;Add a link to the manifest file in &lt;code&gt;index.html&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add the &lt;a href=&quot;https://developer.chrome.com/docs/lighthouse/pwa/themed-omnibox/&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;theme-color&lt;/code&gt;&lt;/a&gt; &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tag to &lt;code&gt;index.html&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Create app icons in the &lt;code&gt;src/assets&lt;/code&gt; directory.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By default, your service worker should be registered within a few seconds of the first page load. If it isn&#39;t, consider modifying the &lt;a href=&quot;https://angular.io/api/service-worker/SwRegistrationOptions&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;registrationStrategy&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;customize-your-pwa&quot;&gt;Customize your PWA &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/creating-pwa-with-angular-cli/#customize-your-pwa&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://web.dev/precaching-with-the-angular-service-worker&quot;&gt;Precaching with the Angular service worker&lt;/a&gt; post explains how to configure the Angular service worker. There you can find how to specify which resources you want the service worker to cache and what strategy it should use to do so.&lt;/p&gt;
&lt;p&gt;The manifest file of your app lets you specify your app&#39;s name, short name, icons, theme color, and other details. Read about the full set of properties you can set on the &lt;a href=&quot;https://web.dev/add-manifest/&quot;&gt;Add a web app manifest&lt;/a&gt; post.&lt;/p&gt;
&lt;p&gt;Take a peek at the manifest file generated by the Angular CLI:&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;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;manifest-web-dev&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;short_name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;manifest-web-dev&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;theme_color&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#1976d2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;background_color&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#fafafa&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;display&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;standalone&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;scope&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;start_url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;icons&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;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;src&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;assets/icons/icon-72x72.png&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;sizes&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;72x72&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;image/png&quot;&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;br /&gt;    …&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;src&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;assets/icons/icon-512x512.png&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;sizes&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;512x512&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;image/png&quot;&lt;/span&gt;&lt;br /&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;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;You can customize any of these properties by changing the relevant value in &lt;code&gt;manifest.webmanifest&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A PWA references its manifest file with a &lt;code&gt;link&lt;/code&gt; element in &lt;code&gt;index.html&lt;/code&gt;. Once the browser finds the reference, it&#39;ll show the &lt;strong&gt;Add to Home screen&lt;/strong&gt; prompt:&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A progressive web app install prompt&quot; decoding=&quot;async&quot; height=&quot;650&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 344px) 344px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/IgMnFCuRU1Fx9JLZWXuT.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/IgMnFCuRU1Fx9JLZWXuT.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/IgMnFCuRU1Fx9JLZWXuT.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/IgMnFCuRU1Fx9JLZWXuT.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/IgMnFCuRU1Fx9JLZWXuT.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/IgMnFCuRU1Fx9JLZWXuT.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/IgMnFCuRU1Fx9JLZWXuT.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/IgMnFCuRU1Fx9JLZWXuT.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/IgMnFCuRU1Fx9JLZWXuT.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/IgMnFCuRU1Fx9JLZWXuT.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/IgMnFCuRU1Fx9JLZWXuT.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/IgMnFCuRU1Fx9JLZWXuT.png?auto=format&amp;w=688 688w&quot; width=&quot;344&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Since the &lt;code&gt;ng-add&lt;/code&gt; schematics add everything needed to make your app &lt;a href=&quot;https://web.dev/discover-installable/&quot;&gt;installable&lt;/a&gt;, they generate some shortcut icons that are shown once the user adds the app to their desktop:&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A progressive web app shortcut icon&quot; decoding=&quot;async&quot; height=&quot;650&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 344px) 344px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/3h7Yuj3MJPiNzbh2xdlB.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/3h7Yuj3MJPiNzbh2xdlB.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/3h7Yuj3MJPiNzbh2xdlB.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/3h7Yuj3MJPiNzbh2xdlB.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/3h7Yuj3MJPiNzbh2xdlB.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/3h7Yuj3MJPiNzbh2xdlB.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/3h7Yuj3MJPiNzbh2xdlB.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/3h7Yuj3MJPiNzbh2xdlB.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/3h7Yuj3MJPiNzbh2xdlB.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/3h7Yuj3MJPiNzbh2xdlB.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/3h7Yuj3MJPiNzbh2xdlB.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/3h7Yuj3MJPiNzbh2xdlB.png?auto=format&amp;w=688 688w&quot; width=&quot;344&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Make sure you customize the manifest properties and icons before you deploy your PWA to production!&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; If you want to change your PWA back to a standard web app, just remove the reference to &lt;code&gt;manifest.webmanifest&lt;/code&gt; from &lt;code&gt;index.html&lt;/code&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/creating-pwa-with-angular-cli/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To make an installable Angular app:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add &lt;code&gt;@angular/pwa&lt;/code&gt; to your project using the Angular CLI.&lt;/li&gt;
&lt;li&gt;Edit the options in the &lt;code&gt;manifest.webmanifest&lt;/code&gt; file to suit your project.&lt;/li&gt;
&lt;li&gt;Update the icons in the &lt;code&gt;src/assets/icons&lt;/code&gt; directory to suit your project.&lt;/li&gt;
&lt;li&gt;Optionally, edit the &lt;code&gt;theme-color&lt;/code&gt; in &lt;code&gt;index.html&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
</content>
    <author>
      <name>Minko Gechev</name>
    </author>
  </entry>
  
  <entry>
    <title>Optimize Angular&#39;s change detection</title>
    <link href="https://web.dev/faster-angular-change-detection/"/>
    <updated>2019-07-09T00:00:00Z</updated>
    <id>https://web.dev/faster-angular-change-detection/</id>
    <content type="html" mode="escaped">&lt;p&gt;Angular runs its &lt;a href=&quot;https://angular.io/api/core/ChangeDetectorRef&quot; rel=&quot;noopener&quot;&gt;change detection mechanism&lt;/a&gt; periodically so that changes to the data model are reflected in an app&#39;s view. Change detection can be triggered either manually or through an asynchronous event (for example, a user interaction or an XHR completion).&lt;/p&gt;
&lt;p&gt;Change detection is a powerful tool, but if it&#39;s run very often, it can trigger a lot of computations and block the main browser thread.&lt;/p&gt;
&lt;p&gt;In this post you&#39;ll learn how to control and optimize the change detection mechanism by skipping parts of your application and running change detection only when necessary.&lt;/p&gt;
&lt;h2 id=&quot;inside-angulars-change-detection&quot;&gt;Inside Angular&#39;s change detection &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/faster-angular-change-detection/#inside-angulars-change-detection&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To understand how Angular&#39;s change detection works, let&#39;s look at a sample app!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can find the code for the app in &lt;a href=&quot;https://github.com/mgechev/change-detection-web-dev&quot; rel=&quot;noopener&quot;&gt;this GitHub repository&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The app lists employees from two departments in a company—sales and R&amp;amp;D—and has two components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AppComponent&lt;/code&gt;, which is the root component of the app, and&lt;/li&gt;
&lt;li&gt;Two instances of &lt;code&gt;EmployeeListComponent&lt;/code&gt;, one for sales and one for R&amp;amp;D.&lt;/li&gt;
&lt;/ul&gt;
&lt;img alt=&quot;Sample application&quot; decoding=&quot;async&quot; height=&quot;456&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/JtDFr3VL1e2AyUvhbKVU.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/JtDFr3VL1e2AyUvhbKVU.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/JtDFr3VL1e2AyUvhbKVU.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/JtDFr3VL1e2AyUvhbKVU.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/JtDFr3VL1e2AyUvhbKVU.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/JtDFr3VL1e2AyUvhbKVU.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/JtDFr3VL1e2AyUvhbKVU.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/JtDFr3VL1e2AyUvhbKVU.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/JtDFr3VL1e2AyUvhbKVU.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/JtDFr3VL1e2AyUvhbKVU.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/JtDFr3VL1e2AyUvhbKVU.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/JtDFr3VL1e2AyUvhbKVU.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/JtDFr3VL1e2AyUvhbKVU.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/JtDFr3VL1e2AyUvhbKVU.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/JtDFr3VL1e2AyUvhbKVU.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/JtDFr3VL1e2AyUvhbKVU.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/JtDFr3VL1e2AyUvhbKVU.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/JtDFr3VL1e2AyUvhbKVU.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;You can see the two instances of &lt;code&gt;EmployeeListComponent&lt;/code&gt; in the template for &lt;code&gt;AppComponent&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;app-employee-list&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;[data]&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;salesList&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;department&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Sales&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;(add)&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;add(salesList, $event)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;(remove)&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;remove(salesList, $event)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;app-employee-list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;app-employee-list&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;[data]&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;rndList&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;department&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;R&amp;amp;D&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;(add)&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;add(rndList, $event)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;(remove)&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;remove(rndList, $event)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;app-employee-list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;For each employee there&#39;s a name and a numeric value. The app passes the employee&#39;s numeric value to a business calculation and visualizes the result on screen.&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;  For simplicity, the app is using an inefficient version of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Fibonacci_number&quot;&gt;fibonacci function&lt;/a&gt; as its calculation to show the implications of heavy bindings in an app.  &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Now take a look at &lt;code&gt;EmployeeListComponent&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;token keyword&quot;&gt;const&lt;/span&gt; fibonacci &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; number&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;number&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;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; num &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&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;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&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;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fibonacci&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fibonacci&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&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;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 function&quot;&gt;Component&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&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;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EmployeeListComponent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  @&lt;span class=&quot;token function&quot;&gt;Input&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; data&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; EmployeeData&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;span class=&quot;token function&quot;&gt;Input&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; department&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; string&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  @&lt;span class=&quot;token function&quot;&gt;Output&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; remove &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EventEmitter&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;EmployeeData&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 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 function&quot;&gt;Output&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; add &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EventEmitter&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;string&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 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 literal-property property&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; string&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;handleKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token literal-property property&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; any&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;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;keyCode &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;13&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;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;emit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;label&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 keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;label &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&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;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;calculate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token literal-property property&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; number&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;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fibonacci&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num&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;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;EmployeeListComponent&lt;/code&gt; accepts a list of employees and a department name as inputs. When the user tries to remove or add an employee, the component triggers a corresponding output. The component also defines the &lt;code&gt;calculate&lt;/code&gt; method, which implements the business calculation.&lt;/p&gt;
&lt;p&gt;Here&#39;s the template for &lt;code&gt;EmployeeListComponent&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Department&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;{{ department }}&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mat-form-field&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;placeholder&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Enter name here&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;matInput&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;[(ngModel)]&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;label&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;(keydown)&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;handleKey($event)&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mat-form-field&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mat-list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mat-list-item&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;*ngFor&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;let item of data&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h3&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;matLine&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;      {{ item.label }}&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;md-chip&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Score&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;mat-chip mat-primary mat-chip-selected&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;primary&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;selected&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;true&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;      {{ calculate(item.num) }}&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;md-chip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mat-list-item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mat-list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This code iterates over all the employees in the list and, for each one, renders a list item. It also includes an &lt;code&gt;ngModel&lt;/code&gt; directive for two-way data binding between the input and the &lt;code&gt;label&lt;/code&gt; property declared in &lt;code&gt;EmployeeListComponent&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;With the two instances of &lt;code&gt;EmployeeListComponent&lt;/code&gt;, the app forms the following component tree:&lt;/p&gt;
&lt;img alt=&quot;Component tree&quot; decoding=&quot;async&quot; height=&quot;454&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/iMfgq2xaKVRcXc3LhWW7.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/iMfgq2xaKVRcXc3LhWW7.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/iMfgq2xaKVRcXc3LhWW7.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/iMfgq2xaKVRcXc3LhWW7.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/iMfgq2xaKVRcXc3LhWW7.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/iMfgq2xaKVRcXc3LhWW7.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/iMfgq2xaKVRcXc3LhWW7.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/iMfgq2xaKVRcXc3LhWW7.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/iMfgq2xaKVRcXc3LhWW7.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/iMfgq2xaKVRcXc3LhWW7.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/iMfgq2xaKVRcXc3LhWW7.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/iMfgq2xaKVRcXc3LhWW7.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/iMfgq2xaKVRcXc3LhWW7.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/iMfgq2xaKVRcXc3LhWW7.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/iMfgq2xaKVRcXc3LhWW7.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/iMfgq2xaKVRcXc3LhWW7.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/iMfgq2xaKVRcXc3LhWW7.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/iMfgq2xaKVRcXc3LhWW7.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;&lt;code&gt;AppComponent&lt;/code&gt; is the root component of the application. Its child components are the two instances of &lt;code&gt;EmployeeListComponent&lt;/code&gt;. Each instance has a list of items (E&lt;sub&gt;1&lt;/sub&gt;, E&lt;sub&gt;2&lt;/sub&gt;, etc.) that represent the individual employees in the department.&lt;/p&gt;
&lt;p&gt;When the user begins entering the name of a new employee in the input box in an&lt;code&gt;EmployeeListComponent&lt;/code&gt;, Angular triggers change detection for the entire component tree starting from &lt;code&gt;AppComponent&lt;/code&gt;. This means that while the user is typing in the text input, Angular is repeatedly recalculating the numeric values associated with each employee to verify that they haven&#39;t changed since the last check.&lt;/p&gt;
&lt;p&gt;To see how slow this can be, open the &lt;a href=&quot;https://stackblitz.com/github/mgechev/change-detection-web-dev&quot; rel=&quot;noopener&quot;&gt;non-optimized version of the project on StackBlitz&lt;/a&gt; and try entering an employee name.&lt;/p&gt;
&lt;p&gt;You can verify that the slowdown comes from the &lt;code&gt;fibonacci&lt;/code&gt; function by setting up the &lt;a href=&quot;https://github.com/mgechev/change-detection-web-dev&quot; rel=&quot;noopener&quot;&gt;example project&lt;/a&gt; and opening the &lt;strong&gt;Performance&lt;/strong&gt; tab of Chrome DevTools.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Press `Control+Shift+J` (or `Command+Option+J` on Mac) to open DevTools.&lt;/li&gt;
&lt;li&gt;Click the &lt;strong&gt;Performance&lt;/strong&gt; tab.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now click &lt;strong&gt;Record&lt;/strong&gt; &lt;span style=&quot;width: 13px;height: 13px;background-color: #6E6E6E;display: inline-block;border-radius: 50%;margin-left: 3px;margin-right: 3px;&quot;&gt;&lt;/span&gt; (in the top-left corner of the &lt;strong&gt;Performance&lt;/strong&gt; panel) and start typing in one of the text boxes in the app. In a few seconds, click &lt;strong&gt;Record&lt;/strong&gt; &lt;span style=&quot;width: 13px;height: 13px;background-color: #6E6E6E;display: inline-block;border-radius: 50%;margin-left: 3px;margin-right: 3px;&quot;&gt;&lt;/span&gt; again to stop recording. Once Chrome DevTools processes all the profiling data it collected, you&#39;ll see something like this:&lt;/p&gt;
&lt;img alt=&quot;Performance profiling&quot; decoding=&quot;async&quot; height=&quot;276&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/1rXcCcnM7rLj183jgQCk.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/1rXcCcnM7rLj183jgQCk.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/1rXcCcnM7rLj183jgQCk.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/1rXcCcnM7rLj183jgQCk.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/1rXcCcnM7rLj183jgQCk.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/1rXcCcnM7rLj183jgQCk.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/1rXcCcnM7rLj183jgQCk.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/1rXcCcnM7rLj183jgQCk.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/1rXcCcnM7rLj183jgQCk.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/1rXcCcnM7rLj183jgQCk.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/1rXcCcnM7rLj183jgQCk.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/1rXcCcnM7rLj183jgQCk.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/1rXcCcnM7rLj183jgQCk.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/1rXcCcnM7rLj183jgQCk.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/1rXcCcnM7rLj183jgQCk.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/1rXcCcnM7rLj183jgQCk.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/1rXcCcnM7rLj183jgQCk.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/1rXcCcnM7rLj183jgQCk.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;If there are many employees in the list, this process may block the browser&#39;s UI thread and cause frame drops, which leads to a bad user experience.&lt;/p&gt;
&lt;h2 id=&quot;skipping-component-subtrees&quot;&gt;Skipping component subtrees &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/faster-angular-change-detection/#skipping-component-subtrees&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When the user is typing in the text input for the &lt;em&gt;sales&lt;/em&gt; &lt;code&gt;EmployeeListComponent&lt;/code&gt; you know that the data in the &lt;em&gt;R&amp;amp;D&lt;/em&gt; department isn&#39;t changing—so there&#39;s no reason to run change detection on its component. To make sure the R&amp;amp;D instance doesn&#39;t trigger change detection, set the &lt;code&gt;changeDetectionStrategy&lt;/code&gt; of &lt;code&gt;EmployeeListComponent&lt;/code&gt; to &lt;code&gt;OnPush&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;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ChangeDetectionStrategy&lt;span class=&quot;token punctuation&quot;&gt;,&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 class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;@angular/core&#39;&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 function&quot;&gt;Component&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;span class=&quot;token literal-property property&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;app-employee-list&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;changeDetection&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ChangeDetectionStrategy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OnPush&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;styleUrls&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 class=&quot;token string&quot;&gt;&#39;employee-list.component.css&#39;&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;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;EmployeeListComponent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Now when the user types in a text input, change detection is only triggered for the corresponding department:&lt;/p&gt;
&lt;img alt=&quot;Change detection in a component subtree&quot; decoding=&quot;async&quot; height=&quot;462&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/1hUupNUByRDQLyYYvMcX.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/1hUupNUByRDQLyYYvMcX.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/1hUupNUByRDQLyYYvMcX.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/1hUupNUByRDQLyYYvMcX.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/1hUupNUByRDQLyYYvMcX.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/1hUupNUByRDQLyYYvMcX.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/1hUupNUByRDQLyYYvMcX.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/1hUupNUByRDQLyYYvMcX.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/1hUupNUByRDQLyYYvMcX.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/1hUupNUByRDQLyYYvMcX.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/1hUupNUByRDQLyYYvMcX.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/1hUupNUByRDQLyYYvMcX.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/1hUupNUByRDQLyYYvMcX.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/1hUupNUByRDQLyYYvMcX.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/1hUupNUByRDQLyYYvMcX.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/1hUupNUByRDQLyYYvMcX.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/1hUupNUByRDQLyYYvMcX.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/1hUupNUByRDQLyYYvMcX.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;&lt;em&gt;You can find this optimization applied to the original application &lt;a href=&quot;https://github.com/mgechev/change-detection-web-dev/tree/onpush&quot; rel=&quot;noopener&quot;&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You can read more about the &lt;code&gt;OnPush&lt;/code&gt; change detection strategy in the &lt;a href=&quot;https://angular.io/api/core/ChangeDetectionStrategy&quot; rel=&quot;noopener&quot;&gt;official Angular documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To see the effect of this optimization, enter a new employee in the &lt;a href=&quot;https://stackblitz.com/github/mgechev/change-detection-web-dev/tree/onpush&quot; rel=&quot;noopener&quot;&gt;application on StackBlitz&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;using-pure-pipes&quot;&gt;Using pure pipes &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/faster-angular-change-detection/#using-pure-pipes&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Even though the change detection strategy for the &lt;code&gt;EmployeeListComponent&lt;/code&gt; is now set to &lt;code&gt;OnPush&lt;/code&gt;, Angular still recalculates the numeric value for all employees in a department when the user types in the corresponding text input.&lt;/p&gt;
&lt;p&gt;To improve this behavior you can take advantage of &lt;a href=&quot;https://angular.io/guide/pipes#pure-and-impure-pipes&quot; rel=&quot;noopener&quot;&gt;pure pipes&lt;/a&gt;. Both pure and impure pipes accept inputs and return results that can be used in a template. The difference between the two is that a pure pipe will recalculate its result only if it receives a different input from its previous invocation.&lt;/p&gt;
&lt;p&gt;Remember that the app calculates a value to display based on the employee&#39;s numeric value, invoking the &lt;code&gt;calculate&lt;/code&gt; method defined in &lt;code&gt;EmployeeListComponent&lt;/code&gt;. If you move the calculation to a pure pipe, Angular will recalculate the pipe expression only when its arguments change. The framework will determine if the arguments of the pipe have changed by performing a reference check. This means that Angular won&#39;t perform any recalculations unless the numeric value for an employee is updated.&lt;/p&gt;
&lt;p&gt;Here&#39;s how to move the business calculation to a pipe called &lt;code&gt;CalculatePipe&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;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Pipe&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PipeTransform &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;@angular/core&#39;&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;const&lt;/span&gt; fibonacci &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; number&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;number&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;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; num &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&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;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&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;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fibonacci&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fibonacci&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&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;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 function&quot;&gt;Pipe&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;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;calculate&#39;&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;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CalculatePipe&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PipeTransform&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token literal-property property&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; number&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;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fibonacci&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;val&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;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The &lt;code&gt;transform&lt;/code&gt; method of the pipe invokes the &lt;code&gt;fibonacci&lt;/code&gt; function. Notice that the pipe is pure. Angular will consider all pipes pure unless you specify otherwise.&lt;/p&gt;
&lt;p&gt;Finally, update the expression inside of the template for &lt;code&gt;EmployeeListComponent&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mat-chip-list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;md-chip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    {{ item.num | calculate }}&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;md-chip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mat-chip-list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;That&#39;s it! Now when the user types in the text input associated with any department, the app won&#39;t recalculate the numeric value for individual employees.&lt;/p&gt;
&lt;p&gt;In the app below you can see how much smoother the typing is!&lt;/p&gt;
&lt;p&gt;To see the effect of the last optimization &lt;a href=&quot;https://stackblitz.com/github/mgechev/change-detection-web-dev/tree/pure-pipe&quot; rel=&quot;noopener&quot;&gt;try this example on StackBlitz&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The code with the pure pipe optimization of the original application is available &lt;a href=&quot;https://github.com/mgechev/change-detection-web-dev/tree/pure-pipe&quot; rel=&quot;noopener&quot;&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/faster-angular-change-detection/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When facing runtime slowdowns in an Angular app:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Profile the application with Chrome DevTools to see where the slowdowns are coming from.&lt;/li&gt;
&lt;li&gt;Introduce the &lt;code&gt;OnPush&lt;/code&gt; change detection strategy to prune a component&#39;s subtrees.&lt;/li&gt;
&lt;li&gt;Move heavy computations to pure pipes to allow the framework to perform caching of the computed values.&lt;/li&gt;
&lt;/ol&gt;
</content>
    <author>
      <name>Minko Gechev</name>
    </author>
  </entry>
  
  <entry>
    <title>Route preloading strategies in Angular</title>
    <link href="https://web.dev/route-preloading-in-angular/"/>
    <updated>2019-07-09T00:00:00Z</updated>
    <id>https://web.dev/route-preloading-in-angular/</id>
    <content type="html" mode="escaped">&lt;p&gt;&lt;a href=&quot;https://web.dev/route-level-code-splitting-in-angular&quot;&gt;Route-level code splitting&lt;/a&gt; can help you reduce the initial load time of an application by delaying the JavaScript associated with routes that aren&#39;t initially needed. This way, the Angular router waits until a user navigates to a given route before triggering a network request to download the associated JavaScript.&lt;/p&gt;
&lt;p&gt;While this technique is great for initial page load, it can slow down navigation, depending on the users&#39; network latency and bandwidth. One way to tackle this problem is &lt;strong&gt;route preloading&lt;/strong&gt;. Using preloading, when the user is at a given route, you can download and cache JavaScript associated with routes that are likely to be needed next. The Angular router provides this functionality out of the box.&lt;/p&gt;
&lt;p&gt;In this post, you&#39;ll learn how to speed up navigation when using route-level code splitting by taking advantage of JavaScript preloading in Angular.&lt;/p&gt;
&lt;h2 id=&quot;route-preloading-strategies-in-angular&quot;&gt;Route preloading strategies in Angular &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/route-preloading-in-angular/#route-preloading-strategies-in-angular&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The Angular router provides a configuration property called &lt;code&gt;preloadingStrategy&lt;/code&gt;, which defines the logic for preloading and processing lazy-loaded Angular modules. We&#39;ll cover two possible strategies:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;PreloadAllModules&lt;/code&gt;, which preloads all lazy-loaded routes, as the name implies&lt;/li&gt;
&lt;li&gt;&lt;code&gt;QuicklinkStrategy&lt;/code&gt;, which preloads only the routes associated with links on the current page.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;The rest of this post refers to a sample Angular app. You can find the source code &lt;a href=&quot;https://github.com/mgechev/route-preloading-web-dev&quot; rel=&quot;noopener&quot;&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;using-the-preloadallmodules-strategy&quot;&gt;Using the &lt;code&gt;PreloadAllModules&lt;/code&gt; strategy &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/route-preloading-in-angular/#using-the-preloadallmodules-strategy&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The sample app has several lazy-loaded routes. To preload all of them using the &lt;code&gt;PreloadAllModules&lt;/code&gt; strategy—which is built into Angular—specify it as the value for the &lt;code&gt;preloadingStrategy&lt;/code&gt; property in the router configuration:&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;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; RouterModule&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PreloadAllModules &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;@angular/router&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// …&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;RouterModule&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forRoot&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 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;span class=&quot;token literal-property property&quot;&gt;preloadingStrategy&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; PreloadAllModules&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;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// …&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Now serve the application and look at the &lt;strong&gt;Network&lt;/strong&gt; panel in Chrome DevTools:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Press `Control+Shift+J` (or `Command+Option+J` on Mac) to open DevTools.&lt;/li&gt;
&lt;li&gt;Click the &lt;strong&gt;Network&lt;/strong&gt; tab.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You should see that the router downloaded &lt;code&gt;nyan-nyan-module.js&lt;/code&gt; and &lt;code&gt;about-about-module.js&lt;/code&gt; in the background when you opened the application:&lt;/p&gt;
&lt;figure&gt;
&lt;video controls=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/tcFciHGuF3MxnTr1y5ue01OGLBn2/TVi6LCasiwZI1hxJrBOL.webm&quot; type=&quot;video/webm&quot; /&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/tcFciHGuF3MxnTr1y5ue01OGLBn2/e9h6JBVl8TUGMWOSAWyC.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;
 &lt;figcaption&gt;
    The PreloadAllModules strategy in action.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The router also registered the modules&#39; route declarations so that when you navigate to a URL associated with any of the preloaded modules, the transition is instantaneous.&lt;/p&gt;
&lt;h3 id=&quot;using-the-quicklink-preloading-strategy&quot;&gt;Using the Quicklink preloading strategy &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/route-preloading-in-angular/#using-the-quicklink-preloading-strategy&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;PreloadAllModules&lt;/code&gt; is useful in a lot of cases. When you have dozens of modules, however, its aggressive preloading can really increase network usage. Also, since the router needs to register the routes in all the preloaded modules, it can cause intensive computations in the UI thread and lead to sluggish user experience.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/GoogleChromeLabs/quicklink&quot; rel=&quot;noopener&quot;&gt;quicklink&lt;/a&gt; library provides a better strategy for larger apps. It uses the &lt;a href=&quot;https://web.dev/intersectionobserver-v2/&quot;&gt;IntersectionObserver&lt;/a&gt; API to preload only modules associated with links that are currently visible on the page.&lt;/p&gt;
&lt;p&gt;You can add quicklink to an Angular app by using the &lt;a href=&quot;https://www.npmjs.com/package/ngx-quicklink&quot; rel=&quot;noopener&quot;&gt;ngx-quicklink&lt;/a&gt; package. Start by installing the package from npm:&lt;/p&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 function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; --save ngx-quicklink&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Once it&#39;s available in your project, you can use &lt;code&gt;QuicklinkStrategy&lt;/code&gt; by specifying the router&#39;s &lt;code&gt;preloadingStrategy&lt;/code&gt; and importing the &lt;code&gt;QuicklinkModule&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;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;QuicklinkStrategy&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; QuicklinkModule&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;ngx-quicklink&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;…&lt;br /&gt;&lt;br /&gt;@&lt;span class=&quot;token function&quot;&gt;NgModule&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 literal-property property&quot;&gt;imports&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;br /&gt;    …&lt;br /&gt;    QuicklinkModule&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    RouterModule&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forRoot&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;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;preloadingStrategy&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; QuicklinkStrategy&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;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;br /&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;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AppModule&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;Now when you open the application again, you&#39;ll notice that the router only preloads &lt;code&gt;nyan-nyan-module.js&lt;/code&gt; since the button in the center of the page has a router link to it. And when you open the side navigation, you&#39;ll notice that the router then preloads the &amp;quot;About&amp;quot; route:&lt;/p&gt;
&lt;figure&gt;
&lt;video controls=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/tcFciHGuF3MxnTr1y5ue01OGLBn2/dfZkoiQyNh4fUj4DJjrc.webm&quot; type=&quot;video/webm&quot; /&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/tcFciHGuF3MxnTr1y5ue01OGLBn2/SkNp99W1Bv2tsaRgOwoe.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;
 &lt;figcaption&gt;
    A demo of the quicklink preloading strategy.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;using-the-quicklink-preloading-strategy-across-multiple-lazy-loaded-modules&quot;&gt;Using the Quicklink preloading strategy across multiple lazy-loaded modules &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/route-preloading-in-angular/#using-the-quicklink-preloading-strategy-across-multiple-lazy-loaded-modules&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The above example will work for a basic application but if your application contains multiple lazy-loaded modules you will need to import the &lt;code&gt;QuicklinkModule&lt;/code&gt; into a shared module, export it and then import the shared module into your lazy-loaded modules.&lt;/p&gt;
&lt;p&gt;First import the &lt;code&gt;QuicklinkModule&lt;/code&gt; from &lt;code&gt;ngx-quicklink&lt;/code&gt; into your shared module and export it:&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;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; QuicklinkModule &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;ngx-quicklink&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;…&lt;br /&gt;&lt;br /&gt;@&lt;span class=&quot;token function&quot;&gt;NgModule&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 literal-property property&quot;&gt;imports&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;br /&gt;    QuicklinkModule&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;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;exports&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;br /&gt;    QuicklinkModule&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;br /&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;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SharedModule&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;Then import your &lt;code&gt;SharedModule&lt;/code&gt; into all of your lazy-loaded modules:&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;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; SharedModule &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;@app/shared/shared.module&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;…&lt;br /&gt;&lt;br /&gt;@&lt;span class=&quot;token function&quot;&gt;NgModule&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 literal-property property&quot;&gt;imports&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;br /&gt;      SharedModule&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;br /&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;&lt;code&gt;Quicklinks&lt;/code&gt; will now be available in your lazy-loaded modules.&lt;/p&gt;
&lt;h2 id=&quot;going-beyond-basic-preloading&quot;&gt;Going beyond basic preloading &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/route-preloading-in-angular/#going-beyond-basic-preloading&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While selective preloading via quicklink can significantly speed up navigation, you can make your preloading strategy even more network efficient by using predictive preloading—which is implemented by &lt;a href=&quot;https://github.com/guess-js/guess&quot; rel=&quot;noopener&quot;&gt;Guess.js&lt;/a&gt;. By analyzing a report from Google Analytics or another analytics provider, Guess.js can predict a user&#39;s navigation journey and preload only the JavaScript chunks that are likely to be needed next.&lt;/p&gt;
&lt;p&gt;You can learn how to use Guess.js with Angular on &lt;a href=&quot;https://guess-js.github.io/docs/angular&quot; rel=&quot;noopener&quot;&gt;this page from the Guess.js site&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/route-preloading-in-angular/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To speed up navigation when using route-level code splitting:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Pick the right preloading strategy depending on the size of your application:
&lt;ul&gt;
&lt;li&gt;Applications with few modules can use Angular&#39;s built-in &lt;code&gt;PreloadAllModules&lt;/code&gt; strategy.&lt;/li&gt;
&lt;li&gt;Applications with many modules should use a custom preloading strategy, like Angular&#39;s quicklink, or predictive preloading, as implemented in Guess.js.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Configure the preloading strategy by setting the &lt;code&gt;preloadStrategy&lt;/code&gt; property of the Angular router.&lt;/li&gt;
&lt;/ol&gt;
</content>
    <author>
      <name>Minko Gechev</name>
    </author>
  </entry>
  
  <entry>
    <title>Faster web navigation with predictive prefetching</title>
    <link href="https://web.dev/predictive-prefetching/"/>
    <updated>2019-07-08T00:00:00Z</updated>
    <id>https://web.dev/predictive-prefetching/</id>
    <content type="html" mode="escaped">&lt;p&gt;In my &lt;a href=&quot;https://www.youtube.com/watch?v=0jB4YWgAxUo&quot; rel=&quot;noopener&quot;&gt;Faster Web Navigation with Predictive Prefetching&lt;/a&gt; session at Google I/O 2019, I began by talking about optimizing web apps with code splitting and the potential performance implications for subsequent page navigation. In the second part of the talk, I discussed how to improve navigation speed by using Guess.js to set up predictive prefetching:&lt;/p&gt;
&lt;div class=&quot;youtube&quot;&gt;  &lt;lite-youtube videoid=&quot;0jB4YWgAxUo&quot;&gt;  &lt;/lite-youtube&gt;&lt;/div&gt;
&lt;h2 id=&quot;code-splitting-for-faster-web-apps&quot;&gt;Code splitting for faster web apps &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/predictive-prefetching/#code-splitting-for-faster-web-apps&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Web apps are slow, and JavaScript is among the most expensive resources that you ship. Waiting for a slow web app to load can frustrate your users and decrease conversions.&lt;/p&gt;
&lt;img alt=&quot;Slow web apps are stressful.&quot; decoding=&quot;async&quot; height=&quot;438&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/Ex1RhD84fTzpNwYM6Ocy.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/Ex1RhD84fTzpNwYM6Ocy.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/Ex1RhD84fTzpNwYM6Ocy.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/Ex1RhD84fTzpNwYM6Ocy.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/Ex1RhD84fTzpNwYM6Ocy.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/Ex1RhD84fTzpNwYM6Ocy.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/Ex1RhD84fTzpNwYM6Ocy.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/Ex1RhD84fTzpNwYM6Ocy.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/Ex1RhD84fTzpNwYM6Ocy.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/Ex1RhD84fTzpNwYM6Ocy.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/Ex1RhD84fTzpNwYM6Ocy.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/Ex1RhD84fTzpNwYM6Ocy.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/Ex1RhD84fTzpNwYM6Ocy.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/Ex1RhD84fTzpNwYM6Ocy.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/Ex1RhD84fTzpNwYM6Ocy.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/Ex1RhD84fTzpNwYM6Ocy.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/Ex1RhD84fTzpNwYM6Ocy.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/Ex1RhD84fTzpNwYM6Ocy.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;Lazy loading is an efficient technique to reduce the bytes of JavaScript that you&#39;re transferring over the wire. You can use several techniques to lazy-load JavaScript, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Component-level code splitting&lt;/li&gt;
&lt;li&gt;Route-level code splitting&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With component-level code splitting, you can move individual components into separate JavaScript chunks. On particular events, you can load the relevant scripts and render the components.&lt;/p&gt;
&lt;p&gt;With route-level code splitting, however, you move entire &lt;em&gt;routes&lt;/em&gt; into independent chunks. When users transition from one route to another, they have to download the associated JavaScript and bootstrap the requested page. These operations can lead to significant delays, especially on slow networks.&lt;/p&gt;
&lt;h2 id=&quot;prefetching-javascript&quot;&gt;Prefetching JavaScript &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/predictive-prefetching/#prefetching-javascript&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Prefetching allows the browser to download and cache resources that the user is likely to need soon. The usual method is to use &lt;code&gt;&amp;lt;link rel=&amp;quot;prefetch&amp;quot;&amp;gt;&lt;/code&gt;, but there are two common pitfalls:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prefetching too many resources (&lt;em&gt;overfetching&lt;/em&gt;) consumes a lot of data.&lt;/li&gt;
&lt;li&gt;Some resources the user needs may never be prefetched.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Predictive prefetching solves these problems by using a report of users&#39; navigational patterns to determine what assets to prefetch.&lt;/p&gt;
&lt;img alt=&quot;Prefetching example&quot; decoding=&quot;async&quot; height=&quot;517&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/vkK5KhZKhSo6bDIBuVrn.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/vkK5KhZKhSo6bDIBuVrn.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/vkK5KhZKhSo6bDIBuVrn.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/vkK5KhZKhSo6bDIBuVrn.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/vkK5KhZKhSo6bDIBuVrn.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/vkK5KhZKhSo6bDIBuVrn.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/vkK5KhZKhSo6bDIBuVrn.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/vkK5KhZKhSo6bDIBuVrn.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/vkK5KhZKhSo6bDIBuVrn.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/vkK5KhZKhSo6bDIBuVrn.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/vkK5KhZKhSo6bDIBuVrn.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/vkK5KhZKhSo6bDIBuVrn.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/vkK5KhZKhSo6bDIBuVrn.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/vkK5KhZKhSo6bDIBuVrn.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/vkK5KhZKhSo6bDIBuVrn.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/vkK5KhZKhSo6bDIBuVrn.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/vkK5KhZKhSo6bDIBuVrn.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/vkK5KhZKhSo6bDIBuVrn.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;h2 id=&quot;predictive-prefetching-with-guessjs&quot;&gt;Predictive prefetching with Guess.js &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/predictive-prefetching/#predictive-prefetching-with-guessjs&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/guess-js&quot; rel=&quot;noopener&quot;&gt;Guess.js&lt;/a&gt; is a JavaScript library that provides predictive prefetching functionality. Guess.js consumes a report from Google Analytics or another analytics provider to build a predictive model that can be used to smartly prefetch only what the user is likely to need.&lt;/p&gt;
&lt;p&gt;Guess.js has integrations with &lt;a href=&quot;https://angular.io/&quot; rel=&quot;noopener&quot;&gt;Angular&lt;/a&gt;, &lt;a href=&quot;https://nextjs.org/&quot; rel=&quot;noopener&quot;&gt;Next.js&lt;/a&gt;, &lt;a href=&quot;https://nuxtjs.org/&quot; rel=&quot;noopener&quot;&gt;Nuxt.js&lt;/a&gt;, and &lt;a href=&quot;https://www.gatsbyjs.org/&quot; rel=&quot;noopener&quot;&gt;Gatsby&lt;/a&gt;. To use it in your application, add these lines to your webpack configuration to specify a &lt;a href=&quot;https://stackoverflow.com/questions/36898103/what-is-a-viewid-in-google-analytics&quot; rel=&quot;noopener&quot;&gt;Google Analytics view ID&lt;/a&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;mark class=&quot;highlight-line highlight-line-active&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; GuessPlugin &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &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;guess-webpack&#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;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;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;GuessPlugin&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 constant&quot;&gt;GA&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;XXXXXX&#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;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 comment&quot;&gt;// ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If you&#39;re not using Google Analytics, you can specify a &lt;code&gt;reportProvider&lt;/code&gt; and download data from your favorite service.&lt;/p&gt;
&lt;h3 id=&quot;integration-with-frameworks&quot;&gt;Integration with frameworks &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/predictive-prefetching/#integration-with-frameworks&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To learn more about how to integrate Guess.js with your favorite framework check out these resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://guess-js.github.io/docs/angular&quot; rel=&quot;noopener&quot;&gt;Using Guess.js with Angular&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://guess-js.github.io/docs/next&quot; rel=&quot;noopener&quot;&gt;Using Guess.js with Next.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://guess-js.github.io/docs/nuxt&quot; rel=&quot;noopener&quot;&gt;Using Guess.js with Nuxt.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For a quick walkthrough on the integration with Angular, check out this video:&lt;/p&gt;
&lt;div class=&quot;youtube&quot;&gt;  &lt;lite-youtube videoid=&quot;5FRxQiGqqmM&quot;&gt;  &lt;/lite-youtube&gt;&lt;/div&gt;
&lt;h3 id=&quot;how-does-guessjs-work&quot;&gt;How does Guess.js work? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/predictive-prefetching/#how-does-guessjs-work&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Here&#39;s how Guess.js implements predictive prefetching:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It first extracts data for the user navigational patterns from your favorite analytics provider.&lt;/li&gt;
&lt;li&gt;It then maps the URLs from the report to the JavaScript chunks produced by webpack.&lt;/li&gt;
&lt;li&gt;Based on the extracted data, it creates a simple predictive model of which pages a user is likely to navigate to from any given page.&lt;/li&gt;
&lt;li&gt;It invokes the model for each JavaScript chunk, predicting the other chunks that are likely to be needed next.&lt;/li&gt;
&lt;li&gt;It adds prefetching instructions to each chunk.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When Guess.js is done, each chunk will contain prefetching instructions similar to:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;__GUESS__&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;p&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 string&quot;&gt;&#39;a.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.2&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;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;b.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.8&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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This Guess.js-generated code is telling the browser to consider prefetching chunk &lt;code&gt;a.js&lt;/code&gt; with probability &lt;code&gt;0.2&lt;/code&gt; and chunk &lt;code&gt;b.js&lt;/code&gt; with probability &lt;code&gt;0.8&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Once the browser executes the code, Guess.js will check the user&#39;s connection speed. If it&#39;s sufficient, Guess.js will insert two &lt;code&gt;&amp;lt;link rel=&amp;quot;prefetch&amp;quot;&amp;gt;&lt;/code&gt; tags in the header of the page, one for each chunk. If the user is on a high-speed network, Guess.js will prefetch both chunks. If the user has a poor network connection, Guess.js will only prefetch chunk &lt;code&gt;b.js&lt;/code&gt; since it has a high probability of being needed.&lt;/p&gt;
&lt;h2 id=&quot;learn-more&quot;&gt;Learn more &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/predictive-prefetching/#learn-more&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To learn more about Guess.js, check out these resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=0jB4YWgAxUo&quot; rel=&quot;noopener&quot;&gt;Faster Web Navigation with Predictive Prefetching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.mgechev.com/2018/05/09/introducing-guess-js-data-driven-user-experiences-web/&quot; rel=&quot;noopener&quot;&gt;Introducing Guess.js - a toolkit for enabling data-driven user-experiences on the Web&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://guess-js.github.io/&quot; rel=&quot;noopener&quot;&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/guess-js&quot; rel=&quot;noopener&quot;&gt;Source code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Minko Gechev</name>
    </author>
  </entry>
  
  <entry>
    <title>Audit your Angular app&#39;s accessibility with codelyzer</title>
    <link href="https://web.dev/accessible-angular-with-codelyzer/"/>
    <updated>2019-07-03T00:00:00Z</updated>
    <id>https://web.dev/accessible-angular-with-codelyzer/</id>
    <content type="html" mode="escaped">&lt;p&gt;Making your app accessible means that all users, including those with special needs, can use it and understand the content. According to the &lt;a href=&quot;https://www.who.int/disabilities/world_report/2011/report.pdf&quot; rel=&quot;noopener&quot;&gt;World Health Report&lt;/a&gt;, more than a billion people—about 15% of the world&#39;s population—have some form of disability. So &lt;a href=&quot;https://web.dev/accessible&quot;&gt;accessibility&lt;/a&gt; is a priority for any development project.&lt;/p&gt;
&lt;p&gt;In this post you&#39;ll learn how to add &lt;a href=&quot;https://github.com/mgechev/codelyzer&quot; rel=&quot;noopener&quot;&gt;codelyzer&#39;s&lt;/a&gt; accessibility checks to the build process for an Angular app. This approach lets you catch accessibility bugs directly in your text editor as you code.&lt;/p&gt;
&lt;h2 id=&quot;using-codelyzer-to-detect-inaccessible-elements&quot;&gt;Using codelyzer to detect inaccessible elements &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/accessible-angular-with-codelyzer/#using-codelyzer-to-detect-inaccessible-elements&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/mgechev/codelyzer&quot; rel=&quot;noopener&quot;&gt;codelyzer&lt;/a&gt; is a tool that sits on top of &lt;a href=&quot;https://palantir.github.io/tslint/&quot; rel=&quot;noopener&quot;&gt;TSLint&lt;/a&gt; and checks whether Angular TypeScript projects follow a set of linting rules. Projects set up with the &lt;a href=&quot;https://cli.angular.io/&quot; rel=&quot;noopener&quot;&gt;Angular command line interface (CLI)&lt;/a&gt; include codelyzer by default.&lt;/p&gt;
&lt;p&gt;codelyzer has over 50 rules for checking if an Angular application follows best practices. Of those, there are about 10 rules for enforcing accessibility criteria. To learn about the various accessibility checks provided by codelyzer and their rationales, see the &lt;a href=&quot;https://medium.com/ngconf/new-accessibility-rules-in-codelyzer-v5-0-0-85eec1d3e9bb&quot; rel=&quot;noopener&quot;&gt;New Accessibility rules in Codelyzer&lt;/a&gt; article.&lt;/p&gt;
&lt;p&gt;Currently, all the accessibility rules are experimental and disabled by default. You can enable them by adding them to the TSLint configuration file (&lt;code&gt;tslint.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 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 property&quot;&gt;&quot;rulesDirectory&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 string&quot;&gt;&quot;codelyzer&quot;&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;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;rules&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 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 property&quot;&gt;&quot;template-accessibility-alt-text&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&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 property&quot;&gt;&quot;template-accessibility-elements-content&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&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 property&quot;&gt;&quot;template-accessibility-label-for&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&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 property&quot;&gt;&quot;template-accessibility-tabindex-no-positive&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&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 property&quot;&gt;&quot;template-accessibility-table-scope&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&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 property&quot;&gt;&quot;template-accessibility-valid-aria&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&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 property&quot;&gt;&quot;template-click-events-have-key-events&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&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 property&quot;&gt;&quot;template-mouse-events-have-key-events&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&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 property&quot;&gt;&quot;template-no-autofocus&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&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 property&quot;&gt;&quot;template-no-distracting-elements&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&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&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;TSLint works with all popular text editors and IDEs. To use it with VSCode, install the &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=eg2.tslint&quot; rel=&quot;noopener&quot;&gt;TSLint plugin&lt;/a&gt;. In WebStorm, TSLint is enabled by default. For other editors, check the TSLint &lt;a href=&quot;https://github.com/palantir/tslint#tslint&quot; rel=&quot;noopener&quot;&gt;README&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With codelyzer&#39;s accessibility checks set up, you get a popup showing accessibility errors in TypeScript files or inline templates as you code:&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A screenshot of a codelyzer popup in a text editor.&quot; decoding=&quot;async&quot; height=&quot;433&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/XArrTmBXfijqQ8AteI76.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/XArrTmBXfijqQ8AteI76.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/XArrTmBXfijqQ8AteI76.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/XArrTmBXfijqQ8AteI76.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/XArrTmBXfijqQ8AteI76.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/XArrTmBXfijqQ8AteI76.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/XArrTmBXfijqQ8AteI76.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/XArrTmBXfijqQ8AteI76.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/XArrTmBXfijqQ8AteI76.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/XArrTmBXfijqQ8AteI76.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/XArrTmBXfijqQ8AteI76.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/XArrTmBXfijqQ8AteI76.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/XArrTmBXfijqQ8AteI76.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/XArrTmBXfijqQ8AteI76.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/XArrTmBXfijqQ8AteI76.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/XArrTmBXfijqQ8AteI76.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/XArrTmBXfijqQ8AteI76.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/XArrTmBXfijqQ8AteI76.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;A codelyzer popup showing a form element labeling error.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;To perform linting over the entire project (including external templates), use the &lt;code&gt;ng lint&lt;/code&gt; command:&lt;/p&gt;
&lt;img alt=&quot;Linting with Angular CLI&quot; decoding=&quot;async&quot; height=&quot;342&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/sZdIj5CNklqppTk0UCf3.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/sZdIj5CNklqppTk0UCf3.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/sZdIj5CNklqppTk0UCf3.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/sZdIj5CNklqppTk0UCf3.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/sZdIj5CNklqppTk0UCf3.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/sZdIj5CNklqppTk0UCf3.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/sZdIj5CNklqppTk0UCf3.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/sZdIj5CNklqppTk0UCf3.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/sZdIj5CNklqppTk0UCf3.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/sZdIj5CNklqppTk0UCf3.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/sZdIj5CNklqppTk0UCf3.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/sZdIj5CNklqppTk0UCf3.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/sZdIj5CNklqppTk0UCf3.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/sZdIj5CNklqppTk0UCf3.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/sZdIj5CNklqppTk0UCf3.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/sZdIj5CNklqppTk0UCf3.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/sZdIj5CNklqppTk0UCf3.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/sZdIj5CNklqppTk0UCf3.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;h2 id=&quot;supplementing-codelyzer&quot;&gt;Supplementing codelyzer &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/accessible-angular-with-codelyzer/#supplementing-codelyzer&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.chrome.com/docs/lighthouse/overview/&quot; rel=&quot;noopener&quot;&gt;Lighthouse&lt;/a&gt; is another tool you can use to enforce accessibility practices in your Angular application. The main difference between codelyzer and Lighthouse is when their checks get performed. Codelyzer statically analyzes the application at development time, without running it. This means that during development you can get direct feedback in your text editor or in the terminal. By contrast, Lighthouse actually runs your application and performs a bunch of checks using dynamic analysis.&lt;/p&gt;
&lt;p&gt;Both tools can be useful parts of your development flow. Lighthouse has better coverage given the checks it performs, while codelyzer allows you to iterate faster by getting constant feedback in your text editor.&lt;/p&gt;
&lt;h2 id=&quot;enforcing-accessibility-checks-in-your-continuous-integration&quot;&gt;Enforcing accessibility checks in your continuous integration &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/accessible-angular-with-codelyzer/#enforcing-accessibility-checks-in-your-continuous-integration&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Introducing static accessibility checks in your continuous integration (CI) can be a great enhancement for your development flow. With codelyzer you can easily enforce certain accessibility rules or other practices by running &lt;code&gt;ng lint&lt;/code&gt; on each code modification (for example for each new pull request).&lt;/p&gt;
&lt;p&gt;This way, even before you proceed to code review, your CI can tell you if there are any accessibility violations.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/accessible-angular-with-codelyzer/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To improve the accessibility of your Angular app:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Enable the experimental accessibility rules in codelyzer.&lt;/li&gt;
&lt;li&gt;Perform accessibility linting over your entire project using the Angular CLI.&lt;/li&gt;
&lt;li&gt;Fix all the accessibility problems reported by codelyzer.&lt;/li&gt;
&lt;li&gt;Consider using Lighthouse for accessibility audits at runtime.&lt;/li&gt;
&lt;/ol&gt;
</content>
    <author>
      <name>Zama Khan Mohammed</name>
    </author><author>
      <name>Minko Gechev</name>
    </author>
  </entry>
  
  <entry>
    <title>Performance budgets with the Angular CLI</title>
    <link href="https://web.dev/performance-budgets-with-the-angular-cli/"/>
    <updated>2019-07-02T00:00:00Z</updated>
    <id>https://web.dev/performance-budgets-with-the-angular-cli/</id>
    <content type="html" mode="escaped">&lt;p&gt;Optimizing an Angular application is important, but how do you make sure its performance doesn&#39;t regress over time? By introducing performance metrics and monitoring them on each code change!&lt;/p&gt;
&lt;p&gt;One important metric is the size of the JavaScript shipped with your application. By introducing a &lt;a href=&quot;https://web.dev/performance-budgets-101&quot;&gt;performance budget&lt;/a&gt; that you monitor on each build or pull request, you can make sure your optimizations persist over time.&lt;/p&gt;
&lt;h2 id=&quot;calculate-your-performance-budget&quot;&gt;Calculate your performance budget &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/performance-budgets-with-the-angular-cli/#calculate-your-performance-budget&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can use &lt;a href=&quot;https://bit.ly/perf-budget-calculator&quot; rel=&quot;noopener&quot;&gt;this online budget calculator&lt;/a&gt; to estimate how much JavaScript your app can afford to load, depending on the &lt;a href=&quot;https://web.dev/tti/&quot;&gt;Time to Interactive&lt;/a&gt; you&#39;re aiming for.&lt;/p&gt;
&lt;img alt=&quot;Budget calculator&quot; decoding=&quot;async&quot; height=&quot;524&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/TWPRBRI7ja8d33unYYK6.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/TWPRBRI7ja8d33unYYK6.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/TWPRBRI7ja8d33unYYK6.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/TWPRBRI7ja8d33unYYK6.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/TWPRBRI7ja8d33unYYK6.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/TWPRBRI7ja8d33unYYK6.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/TWPRBRI7ja8d33unYYK6.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/TWPRBRI7ja8d33unYYK6.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/TWPRBRI7ja8d33unYYK6.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/TWPRBRI7ja8d33unYYK6.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/TWPRBRI7ja8d33unYYK6.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/TWPRBRI7ja8d33unYYK6.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/TWPRBRI7ja8d33unYYK6.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/TWPRBRI7ja8d33unYYK6.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/TWPRBRI7ja8d33unYYK6.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/TWPRBRI7ja8d33unYYK6.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/TWPRBRI7ja8d33unYYK6.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/TWPRBRI7ja8d33unYYK6.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;h2 id=&quot;configure-a-performance-budget-in-the-angular-cli&quot;&gt;Configure a performance budget in the Angular CLI &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/performance-budgets-with-the-angular-cli/#configure-a-performance-budget-in-the-angular-cli&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Once you have a target JavaScript budget, you can enforce it using the &lt;a href=&quot;https://cli.angular.io/&quot; rel=&quot;noopener&quot;&gt;Angular command line interface (CLI)&lt;/a&gt;. To see how that works, check out &lt;a href=&quot;https://github.com/mgechev/budgets-web-dev/blob/master/angular.json#L33-L38&quot; rel=&quot;noopener&quot;&gt;this sample app on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You&#39;ll see that the following budget has been configured in &lt;code&gt;angular.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;token property&quot;&gt;&quot;budgets&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 class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;bundle&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;main&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;maximumWarning&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;170kb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;maximumError&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;250kb&quot;&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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Here&#39;s a summary of what&#39;s being specified:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There&#39;s a budget for a JavaScript bundle called &lt;code&gt;main&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If the &lt;code&gt;main&lt;/code&gt; bundle gets bigger than 170 KB, the Angular CLI will show a warning in the console when you build the app.&lt;/li&gt;
&lt;li&gt;If the &lt;code&gt;main&lt;/code&gt; bundle gets bigger than 250 KB, the build will fail.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now try building the app by running &lt;code&gt;ng build --prod&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You should see this error in the console:&lt;/p&gt;
&lt;img alt=&quot;Budget failure&quot; decoding=&quot;async&quot; height=&quot;258&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/KXJS3kX1XGnItcrS8HJS.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/KXJS3kX1XGnItcrS8HJS.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/KXJS3kX1XGnItcrS8HJS.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/KXJS3kX1XGnItcrS8HJS.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/KXJS3kX1XGnItcrS8HJS.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/KXJS3kX1XGnItcrS8HJS.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/KXJS3kX1XGnItcrS8HJS.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/KXJS3kX1XGnItcrS8HJS.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/KXJS3kX1XGnItcrS8HJS.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/KXJS3kX1XGnItcrS8HJS.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/KXJS3kX1XGnItcrS8HJS.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/KXJS3kX1XGnItcrS8HJS.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/KXJS3kX1XGnItcrS8HJS.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/KXJS3kX1XGnItcrS8HJS.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/KXJS3kX1XGnItcrS8HJS.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/KXJS3kX1XGnItcrS8HJS.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/KXJS3kX1XGnItcrS8HJS.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/KXJS3kX1XGnItcrS8HJS.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;To fix the build error, take a look at &lt;code&gt;app.component.ts&lt;/code&gt;, which includes an import from &lt;code&gt;rxjs/internal/operators&lt;/code&gt;. This is a private import that&#39;s not supposed to be used by consumers of &lt;code&gt;rxjs&lt;/code&gt;. It increases the bundle size a lot! When you update to the correct import, &lt;code&gt;rxjs/operators&lt;/code&gt;, and run the build again, you&#39;ll see that it passes the budget check successfully.&lt;/p&gt;
&lt;p&gt;Note that, since &lt;a href=&quot;https://dev.to/lacolaco/differential-loading-a-new-feature-of-angular-cli-v8-4jl&quot; rel=&quot;noopener&quot;&gt;differential loading&lt;/a&gt; is enabled by default in the Angular CLI, the &lt;code&gt;ng build&lt;/code&gt; command produces two builds of the app:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A build for browsers &lt;em&gt;with&lt;/em&gt; ECMAScript 2015 support. This build includes fewer polyfills and more modern JavaScript syntax. That syntax is more expressive, which leads to smaller bundles.&lt;/li&gt;
&lt;li&gt;A build for older browsers &lt;em&gt;without&lt;/em&gt; ECMAScript 2015 support. The older syntax is less expressive and requires more polyfills, which leads to larger bundles.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;index.html&lt;/code&gt; file of the sample app refers to both builds so that modern browsers can take advantage of the smaller ECMAScript 2015 build and older browsers can fall back to the ECMAScript 5 build.&lt;/p&gt;
&lt;h2 id=&quot;enforce-your-budget-as-part-of-continuous-integration&quot;&gt;Enforce your budget as part of continuous integration &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/performance-budgets-with-the-angular-cli/#enforce-your-budget-as-part-of-continuous-integration&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Continuous_integration&quot; rel=&quot;noopener&quot;&gt;Continuous integration (CI)&lt;/a&gt; offers a convenient way to monitor the budget of your app over time. And, luckily, the quickest way to set that up is to build your app with the Angular CLI—no extra steps required! Whenever the JavaScript bundle exceeds the budget, the process will exit with code 1, and the build will fail.&lt;/p&gt;
&lt;p&gt;If you prefer, you can also enforce a performance budget using &lt;a href=&quot;https://github.com/siddharthkp/bundlesize&quot; rel=&quot;noopener&quot;&gt;bundlesize&lt;/a&gt; and &lt;a href=&quot;https://web.dev/using-lighthouse-bot-to-set-a-performance-budget/&quot;&gt;Lighthouse&lt;/a&gt;. The main difference between performance budgets in the Angular CLI and Lighthouse is when the checks get performed. The Angular CLI performs the checks at build time, looking at the production assets and verifying their sizes. Lighthouse, however, opens the deployed version of the application and measures the asset size. Both approaches have their pros and cons. The check that Angular CLI performs is less robust but much faster since it&#39;s a single disk lookup. On the other hand, the LightWallet of Lighthouse can perform a very accurate check by considering dynamically loaded resources, but it needs to deploy and open the app each time it runs.&lt;/p&gt;
&lt;p&gt;bundlesize is quite similar to the Angular CLI&#39;s budget check; the main difference is that bundlesize can show the check results directly in GitHub&#39;s user interface.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/performance-budgets-with-the-angular-cli/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Establish performance budgets with the Angular CLI to make sure your Angular app&#39;s performance doesn&#39;t regress over time:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Set a baseline for the resource size either by using a budget calculator or by following your organization&#39;s practices.&lt;/li&gt;
&lt;li&gt;Configure size budgets in &lt;code&gt;angular.json&lt;/code&gt; under &lt;code&gt;projects.[PROJECT-NAME].architect.build.configurations.production.budgets&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The budgets will be automatically enforced on each build with the Angular CLI.&lt;/li&gt;
&lt;li&gt;Consider introducing budget monitoring as part of continuous integration (which can also be achieved with the Angular CLI).&lt;/li&gt;
&lt;/ol&gt;
</content>
    <author>
      <name>Minko Gechev</name>
    </author>
  </entry>
  
  <entry>
    <title>Precaching with the Angular service worker</title>
    <link href="https://web.dev/precaching-with-the-angular-service-worker/"/>
    <updated>2019-07-02T00:00:00Z</updated>
    <id>https://web.dev/precaching-with-the-angular-service-worker/</id>
    <content type="html" mode="escaped">&lt;h2 id=&quot;dealing-with-limited-connectivity&quot;&gt;Dealing with limited connectivity &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/precaching-with-the-angular-service-worker/#dealing-with-limited-connectivity&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When users have limited network access—or none at all—web app functionality can significantly degrade and often fails. Using a &lt;a href=&quot;https://developer.chrome.com/docs/workbox/service-worker-overview/&quot; rel=&quot;noopener&quot;&gt;service worker&lt;/a&gt; to provide precaching lets you intercept network requests and deliver responses directly from a local cache instead of retrieving them from the network. Once your app&#39;s assets have been cached, this approach can really speed up an app and make it work when the user is offline.&lt;/p&gt;
&lt;p&gt;This post walks through how to set up precaching in an Angular app. It assumes you&#39;re already familiar with precaching and service workers in general. If you need a refresher, check out the &lt;a href=&quot;https://web.dev/service-workers-cache-storage/&quot;&gt;Service workers and the Cache Storage API&lt;/a&gt; post.&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;  &lt;em&gt;You can find the code for the current example &lt;a href=&quot;https://github.com/mgechev/service-worker-web-dev&quot;&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;  &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;introducing-the-angular-service-worker&quot;&gt;Introducing the Angular service worker &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/precaching-with-the-angular-service-worker/#introducing-the-angular-service-worker&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The Angular team offers a service worker module with precaching functionality that&#39;s well integrated with the framework and the &lt;a href=&quot;https://cli.angular.io/&quot; rel=&quot;noopener&quot;&gt;Angular command line interface (CLI)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To add the service worker, run this command in the CLI:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;ng &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; @angular/pwa&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  If you have multiple projects in the Angular CLI workspace, you can optionally specify a &lt;code&gt;--project&lt;/code&gt; property with the project name you want to add the service worker to.  &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;&lt;code&gt;@angular/service-worker&lt;/code&gt; and &lt;code&gt;@angular/pwa&lt;/code&gt; should now be installed in the app and should appear in &lt;code&gt;package.json&lt;/code&gt;. The &lt;code&gt;ng-add&lt;/code&gt; &lt;a href=&quot;https://angular.io/guide/schematics&quot; rel=&quot;noopener&quot;&gt;schematic&lt;/a&gt; also adds a file called &lt;code&gt;ngsw-config.json&lt;/code&gt; to the project, which you can use to configure the service worker. (The file includes a default configuration that you&#39;ll customize a little later.)&lt;/p&gt;
&lt;p&gt;Now build the project for production:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;ng build --prod&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Inside the &lt;code&gt;dist/service-worker-web-dev&lt;/code&gt; directory you&#39;ll find a file called &lt;code&gt;ngsw.json&lt;/code&gt;. This file tells the Angular service worker how to cache the assets in the app. The file is generated during the build process based on the configuration (&lt;code&gt;ngsw-config.json&lt;/code&gt;) and the assets produced at build time.&lt;/p&gt;
&lt;p&gt;Now start an HTTP server in the directory containing your app&#39;s production assets, open the public URL, and check out its network requests in Chrome DevTools:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Press `Control+Shift+J` (or `Command+Option+J` on Mac) to open DevTools.&lt;/li&gt;
&lt;li&gt;Click the &lt;strong&gt;Network&lt;/strong&gt; tab.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note that the network tab has a bunch of static assets directly downloaded in the background by the &lt;code&gt;ngsw-worker.js&lt;/code&gt; script:&lt;/p&gt;
&lt;img alt=&quot;Sample app&quot; decoding=&quot;async&quot; height=&quot;599&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/XL0o6p4YbQiBJmWW8Kw4.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/XL0o6p4YbQiBJmWW8Kw4.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/XL0o6p4YbQiBJmWW8Kw4.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/XL0o6p4YbQiBJmWW8Kw4.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/XL0o6p4YbQiBJmWW8Kw4.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/XL0o6p4YbQiBJmWW8Kw4.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/XL0o6p4YbQiBJmWW8Kw4.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/XL0o6p4YbQiBJmWW8Kw4.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/XL0o6p4YbQiBJmWW8Kw4.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/XL0o6p4YbQiBJmWW8Kw4.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/XL0o6p4YbQiBJmWW8Kw4.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/XL0o6p4YbQiBJmWW8Kw4.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/XL0o6p4YbQiBJmWW8Kw4.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/XL0o6p4YbQiBJmWW8Kw4.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/XL0o6p4YbQiBJmWW8Kw4.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/XL0o6p4YbQiBJmWW8Kw4.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/XL0o6p4YbQiBJmWW8Kw4.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/XL0o6p4YbQiBJmWW8Kw4.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;This is the Angular service worker precaching the static assets specified in the generated &lt;code&gt;ngsw.json&lt;/code&gt; manifest file.&lt;/p&gt;
&lt;p&gt;One important asset is missing though: &lt;code&gt;nyan.png&lt;/code&gt;. To precache this image you need to add a pattern that includes it to &lt;code&gt;ngsw-config.json&lt;/code&gt;, which lives in the root of the workspace:&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 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 property&quot;&gt;&quot;$schema&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./node_modules/@angular/service-worker/config/schema.json&quot;&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 property&quot;&gt;&quot;index&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/index.html&quot;&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 property&quot;&gt;&quot;assetGroups&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 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 property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;app&quot;&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 property&quot;&gt;&quot;installMode&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;prefetch&quot;&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 property&quot;&gt;&quot;resources&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 property&quot;&gt;&quot;files&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 string&quot;&gt;&quot;/favicon.ico&quot;&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 string&quot;&gt;&quot;/index.html&quot;&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 string&quot;&gt;&quot;/*.css&quot;&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 string&quot;&gt;&quot;/*.js&quot;&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 string&quot;&gt;&quot;/assets/*.png&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&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;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 punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This change adds all PNG images in the &lt;code&gt;/assets&lt;/code&gt; folder  to the &lt;code&gt;app&lt;/code&gt; resource asset group. Since the &lt;code&gt;installMode&lt;/code&gt; for this asset group is set to &lt;code&gt;prefetch&lt;/code&gt;, the service worker will precache all the specified assets—which now include PNG images.&lt;/p&gt;
&lt;p&gt;Specifying other assets to be precached is just as straightforward: update the patterns in the &lt;code&gt;app&lt;/code&gt; resource asset group.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/precaching-with-the-angular-service-worker/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Using a service worker for precaching can improve the performance of your apps by saving assets to a local cache, which makes them more reliable on poor networks. To use precaching with Angular and the Angular CLI:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add the &lt;code&gt;@angular/pwa&lt;/code&gt; package to your project.&lt;/li&gt;
&lt;li&gt;Control what the service worker caches by editing &lt;code&gt;ngsw-config.json&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
</content>
    <author>
      <name>Minko Gechev</name>
    </author>
  </entry>
  
  <entry>
    <title>Get started: optimize an Angular application</title>
    <link href="https://web.dev/get-started-optimize-angular/"/>
    <updated>2019-06-24T00:00:00Z</updated>
    <id>https://web.dev/get-started-optimize-angular/</id>
    <content type="html" mode="escaped">&lt;h2 id=&quot;whats-angular&quot;&gt;What&#39;s Angular? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/get-started-optimize-angular/#whats-angular&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Angular is a framework for building user interfaces. It provides building blocks to help you quickly set up a maintainable, scalable application. Angular empowers developers to create applications that live on the web, mobile, or the desktop.&lt;/p&gt;
&lt;h2 id=&quot;whats-in-this-collection&quot;&gt;What&#39;s in this collection? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/get-started-optimize-angular/#whats-in-this-collection&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This collection focuses on five major areas for optimizing an Angular application:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Improving the &lt;strong&gt;performance&lt;/strong&gt; of your application to increase user conversion and engagement&lt;/li&gt;
&lt;li&gt;Improving your application&#39;s &lt;strong&gt;reliability&lt;/strong&gt; on poor networks by precaching assets with the Angular service worker&lt;/li&gt;
&lt;li&gt;Making your application &lt;strong&gt;discoverable&lt;/strong&gt; for search engines and social media bots using prerendering and server-side rendering&lt;/li&gt;
&lt;li&gt;Making your application &lt;strong&gt;installable&lt;/strong&gt; to provide a user experience similar to an iOS/Android app&#39;s&lt;/li&gt;
&lt;li&gt;Improving the &lt;strong&gt;accessibility of&lt;/strong&gt; your application to make it usable and understandable for all users&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each post in the collection will describe techniques that you can directly apply to your own applications.&lt;/p&gt;
&lt;h2 id=&quot;whats-not-in-this-collection&quot;&gt;What&#39;s &lt;em&gt;not&lt;/em&gt; in this collection? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/get-started-optimize-angular/#whats-not-in-this-collection&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This collection assumes that you&#39;re already familiar with Angular and TypeScript. If you&#39;re not feeling confident with them yet, check out the TypeScript &lt;a href=&quot;https://www.typescriptlang.org/docs/home.html&quot; rel=&quot;noopener&quot;&gt;documentation&lt;/a&gt; and the &lt;a href=&quot;https://angular.io/start&quot; rel=&quot;noopener&quot;&gt;Getting Started with Angular&lt;/a&gt; guide on &lt;a href=&quot;https://angular.io/&quot; rel=&quot;noopener&quot;&gt;angular.io&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;start-a-project&quot;&gt;Start a project &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/get-started-optimize-angular/#start-a-project&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://cli.angular.io/&quot; rel=&quot;noopener&quot;&gt;Angular command line interface (CLI)&lt;/a&gt; lets you quickly set up a simple client-side Angular application. This post has a short introduction to the CLI, while other posts in the collection show how to add more advanced features like server-side rendering and deployment support.&lt;/p&gt;
&lt;h3 id=&quot;set-up-the-cli&quot;&gt;Set up the CLI &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/get-started-optimize-angular/#set-up-the-cli&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To begin, install the CLI globally and verify that you have the latest version by running these commands:&lt;/p&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 function&quot;&gt;npm&lt;/span&gt; i -g @angular/cli&lt;br /&gt;ng --version&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Make sure the last command outputs version 8.0.3 or newer.&lt;/p&gt;
&lt;p&gt;Alternatively, if you don&#39;t want to install the CLI globally, you can install it locally and run it with the &lt;code&gt;npx&lt;/code&gt; command:&lt;/p&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 function&quot;&gt;npm&lt;/span&gt; i @angular/cli&lt;br /&gt;npx ng --version&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;create-the-project&quot;&gt;Create the project &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/get-started-optimize-angular/#create-the-project&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To create a new project run:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;ng new my-app&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This command will create the initial files and folder structure for your application and install the node modules it needs.&lt;/p&gt;
&lt;p&gt;Once the setup process completes successfully, start your application by running:&lt;/p&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; my-app&lt;br /&gt;ng serve&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;You should now be able to access your application at &lt;a href=&quot;http://localhost:4200/&quot; rel=&quot;noopener&quot;&gt;http://localhost:4200&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;whats-next&quot;&gt;What&#39;s next? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/get-started-optimize-angular/#whats-next&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the rest of this collection you&#39;ll learn how to improve the performance, accessibility, and SEO of your Angular application. Here&#39;s what&#39;s covered:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Route-Level code splitting in Angular&lt;/li&gt;
&lt;li&gt;Performance Budgets with the Angular CLI&lt;/li&gt;
&lt;li&gt;Route Prefetching Strategies in Angular&lt;/li&gt;
&lt;li&gt;Change detection optimization in Angular&lt;/li&gt;
&lt;li&gt;Virtualize large lists with the Angular CDK&lt;/li&gt;
&lt;li&gt;Precaching with the Angular Service Worker&lt;/li&gt;
&lt;li&gt;Pre-render routes with Angular CLI&lt;/li&gt;
&lt;li&gt;Server-side rendering with Angular Universal&lt;/li&gt;
&lt;li&gt;Add a web app manifest with Angular CLI&lt;/li&gt;
&lt;li&gt;Accessibility auditing with codelyzer&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Minko Gechev</name>
    </author>
  </entry>
  
  <entry>
    <title>Route-level code splitting in Angular</title>
    <link href="https://web.dev/route-level-code-splitting-in-angular/"/>
    <updated>2019-06-24T00:00:00Z</updated>
    <id>https://web.dev/route-level-code-splitting-in-angular/</id>
    <content type="html" mode="escaped">&lt;p&gt;This post explains how to set up route-level &lt;a href=&quot;https://web.dev/reduce-javascript-payloads-with-code-splitting/&quot;&gt;code splitting&lt;/a&gt; in an Angular application, which can reduce JavaScript bundle size and dramatically improve &lt;a href=&quot;https://web.dev/tti/&quot;&gt;Time to Interactive&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can find the code samples from this article on &lt;a href=&quot;https://github.com/mgechev/code-splitting-web-dev&quot; rel=&quot;noopener&quot;&gt;GitHub&lt;/a&gt;. The eager routing example is available in the &lt;a href=&quot;https://github.com/mgechev/code-splitting-web-dev/tree/eager&quot; rel=&quot;noopener&quot;&gt;eager branch&lt;/a&gt;. The route-level code splitting example is in the &lt;a href=&quot;https://github.com/mgechev/code-splitting-web-dev/tree/lazy&quot; rel=&quot;noopener&quot;&gt;lazy branch&lt;/a&gt;.&lt;/em&gt;&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; This post assumes understanding of the Angular router. For a guide on how to use it, visit Angular&#39;s &lt;a href=&quot;https://angular.io/guide/router&quot;&gt;official documentation&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;why-code-splitting-matters&quot;&gt;Why code splitting matters &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/route-level-code-splitting-in-angular/#why-code-splitting-matters&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The ever growing complexity of web applications has led to a significant increase in the amount of JavaScript shipped to users. Large JavaScript files can noticeably delay interactivity, so it can be a costly resource, especially on mobile.&lt;/p&gt;
&lt;p&gt;The most efficient way to shrink JavaScript bundles without sacrificing features in your applications is to introduce aggressive code splitting.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://web.dev/reduce-javascript-payloads-with-code-splitting/&quot;&gt;Code splitting&lt;/a&gt;&lt;/strong&gt; lets you divide the JavaScript of your application into multiple chunks associated with different routes or features. This approach only sends users the JavaScript they need during the initial application load, keeping load times low.&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;  By using code splitting, &lt;a href=&quot;https://medium.com/@addyosmani/the-cost-of-javascript-in-2018-7d8950fbb5d4&quot;&gt;Twitter and Tinder&lt;/a&gt; observed improvements of up to 50% for their &lt;a href=&quot;https://web.dev/tti/&quot;&gt;Time to Interactive&lt;/a&gt;.  &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;code-splitting-techniques&quot;&gt;Code splitting techniques &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/route-level-code-splitting-in-angular/#code-splitting-techniques&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Code splitting can be done at two levels: the &lt;strong&gt;component level&lt;/strong&gt; and the &lt;strong&gt;route level&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In component-level code splitting, you move components to their own JavaScript chunks and load them lazily when they are needed.&lt;/li&gt;
&lt;li&gt;In route-level code splitting, you encapsulate the functionality of each route into a separate chunk. When users navigate your application they fetch the chunks associated with the individual routes and get the associated functionality when they need it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This post focuses on setting up route-level splitting in Angular.&lt;/p&gt;
&lt;h3 id=&quot;sample-application&quot;&gt;Sample application &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/route-level-code-splitting-in-angular/#sample-application&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Before digging into how to use route level code splitting in Angular, let&#39;s look at a sample app:&lt;/p&gt;
&lt;div class=&quot;glitch-embed-wrap&quot; style=&quot;height: 480px; width: 100%;&quot;&gt;
  &lt;iframe allow=&quot;&quot; loading=&quot;lazy&quot; src=&quot;https://stackblitz.com/github/mgechev/code-splitting-web-dev/tree/eager?embed=1&amp;file=src/app/app.component.ts&amp;view=preview&quot; style=&quot;height: 100%; width: 100%; border: 0;&quot; title=&quot;IFrame content&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;Check out the implementation of the app&#39;s modules. Inside &lt;code&gt;AppModule&lt;/code&gt; two routes are defined: the default route associated with &lt;code&gt;HomeComponent&lt;/code&gt; and a &lt;code&gt;nyan&lt;/code&gt; route associated with &lt;code&gt;NyanComponent&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;@&lt;span class=&quot;token function&quot;&gt;NgModule&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;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;imports&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;br /&gt;    BrowserModule&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    RouterModule&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forRoot&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;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; HomeComponent&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;pathMatch&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;full&#39;&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;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;nyan&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; NyanComponent&lt;br /&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;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;br /&gt;  &lt;span class=&quot;token operator&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;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AppModule&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;h3 id=&quot;route-level-code-splitting&quot;&gt;Route-level code splitting &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/route-level-code-splitting-in-angular/#route-level-code-splitting&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To set up code splitting, the &lt;code&gt;nyan&lt;/code&gt; eager route needs to be refactored.&lt;/p&gt;
&lt;p&gt;Version 8.1.0 of the Angular CLI can do everything for you with this command:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;ng g module nyan --module app --route nyan&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This will generate:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A new routing module called &lt;code&gt;NyanModule&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A route in &lt;code&gt;AppModule&lt;/code&gt; called &lt;code&gt;nyan&lt;/code&gt; that will dynamically load the &lt;code&gt;NyanModule&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A default route in the &lt;code&gt;NyanModule&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A component called &lt;code&gt;NyanComponent&lt;/code&gt; that will be rendered when the user hits the default route&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&#39;s go through these steps manually so we get a better understanding of implementing code splitting with Angular!&lt;/p&gt;
&lt;p&gt;When the user navigates to the &lt;code&gt;nyan&lt;/code&gt; route, the router will render the &lt;code&gt;NyanComponent&lt;/code&gt; in the router outlet.&lt;/p&gt;
&lt;p&gt;To use route-level code splitting in Angular, set the &lt;code&gt;loadChildren&lt;/code&gt; property of the route declaration and combine it with a dynamic import:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&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 literal-property property&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;nyan&#39;&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 function-variable function&quot;&gt;loadChildren&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 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 keyword&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;./nyan/nyan.module&#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;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; m&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;NyanModule&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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;There are a two key differences from the eager route:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You set &lt;code&gt;loadChildren&lt;/code&gt; instead of &lt;code&gt;component&lt;/code&gt;. When using route-level code splitting you need to point to dynamically loaded modules, instead of components.&lt;/li&gt;
&lt;li&gt;In &lt;code&gt;loadChildren&lt;/code&gt;, once the promise is resolved you return the &lt;code&gt;NyanModule&lt;/code&gt; instead of pointing to the &lt;code&gt;NyanComponent&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The snippet above specifies that when the user navigates to &lt;code&gt;nyan&lt;/code&gt;, Angular should dynamically load &lt;code&gt;nyan.module&lt;/code&gt; from the &lt;code&gt;nyan&lt;/code&gt; directory and render the component associated with the default route declared in the module.&lt;/p&gt;
&lt;p&gt;You can associate the default route with a component using this declaration:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; NgModule &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;@angular/core&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; NyanComponent &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;./nyan.component&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; RouterModule &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;@angular/router&#39;&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 function&quot;&gt;NgModule&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;span class=&quot;token literal-property property&quot;&gt;declarations&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;NyanComponent&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 literal-property property&quot;&gt;imports&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;br /&gt;    RouterModule&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forChild&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;span class=&quot;token literal-property property&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;pathMatch&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;full&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; NyanComponent&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;br /&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;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NyanModule&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;This code renders &lt;code&gt;NyanComponent&lt;/code&gt; when the user navigates to &lt;code&gt;https://example.com/nyan&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To check that the Angular router downloads the &lt;code&gt;nyan.module&lt;/code&gt; lazily in your local environment:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Press `Control+Shift+J` (or `Command+Option+J` on Mac) to open DevTools.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click the &lt;strong&gt;Network&lt;/strong&gt; tab.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click &lt;strong&gt;NYAN&lt;/strong&gt; in the sample app.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Note that the &lt;code&gt;nyan-nyan-module.js&lt;/code&gt; file appears in the network tab.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;img alt=&quot;Lazy-loading of JavaScript bundles with route-level code splitting&quot; decoding=&quot;async&quot; height=&quot;524&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/wT4xLV2OkrZ2b7QaQz8L.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/wT4xLV2OkrZ2b7QaQz8L.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/wT4xLV2OkrZ2b7QaQz8L.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/wT4xLV2OkrZ2b7QaQz8L.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/wT4xLV2OkrZ2b7QaQz8L.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/wT4xLV2OkrZ2b7QaQz8L.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/wT4xLV2OkrZ2b7QaQz8L.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/wT4xLV2OkrZ2b7QaQz8L.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/wT4xLV2OkrZ2b7QaQz8L.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/wT4xLV2OkrZ2b7QaQz8L.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/wT4xLV2OkrZ2b7QaQz8L.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/wT4xLV2OkrZ2b7QaQz8L.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/wT4xLV2OkrZ2b7QaQz8L.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/wT4xLV2OkrZ2b7QaQz8L.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/wT4xLV2OkrZ2b7QaQz8L.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/wT4xLV2OkrZ2b7QaQz8L.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/wT4xLV2OkrZ2b7QaQz8L.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/wT4xLV2OkrZ2b7QaQz8L.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;&lt;em&gt;Find this example &lt;a href=&quot;https://github.com/mgechev/code-splitting-web-dev/tree/lazy/src&quot; rel=&quot;noopener&quot;&gt;on GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;show-a-spinner&quot;&gt;Show a spinner &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/route-level-code-splitting-in-angular/#show-a-spinner&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Right now, when the user clicks the &lt;strong&gt;NYAN&lt;/strong&gt; button, the application doesn&#39;t indicate that it&#39;s loading JavaScript in the background. To give the user feedback while loading the script you&#39;ll probably want to add a spinner.&lt;/p&gt;
&lt;p&gt;To do that, start by adding markup for the indicator inside the &lt;code&gt;router-outlet&lt;/code&gt; element in &lt;code&gt;app.component.html&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;router-outlet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;loader&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;*ngIf&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;loading&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;router-outlet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Then add an &lt;code&gt;AppComponent&lt;/code&gt; class to handle routing events. This class will set the &lt;code&gt;loading&lt;/code&gt; flag to &lt;code&gt;true&lt;/code&gt; when it hears the &lt;code&gt;RouteConfigLoadStart&lt;/code&gt; event and set the flag to &lt;code&gt;false&lt;/code&gt; when it hears the &lt;code&gt;RouteConfigLoadEnd&lt;/code&gt; event.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;@&lt;span class=&quot;token function&quot;&gt;Component&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;span class=&quot;token literal-property property&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;app-root&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;templateUrl&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;./app.component.html&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;styleUrls&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 class=&quot;token string&quot;&gt;&#39;./app.component.css&#39;&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;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AppComponent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;loading&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; boolean&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token literal-property property&quot;&gt;router&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Router&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;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;loading &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;events&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;subscribe&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;event&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; RouterEvent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&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;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NavigationStart&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;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;loading &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&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 keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NavigationEnd&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;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;loading &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&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;br /&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;br /&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;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;In the example below we&#39;ve introduced an artificial 500 ms latency so that you can see the spinner in action.&lt;/p&gt;
&lt;div class=&quot;glitch-embed-wrap&quot; style=&quot;height: 480px; width: 100%;&quot;&gt;
  &lt;iframe allow=&quot;&quot; loading=&quot;lazy&quot; src=&quot;https://stackblitz.com/github/mgechev/code-splitting-web-dev/tree/lazy?embed=1&amp;file=src/app/app.component.ts&amp;view=preview&quot; style=&quot;height: 100%; width: 100%; border: 0;&quot; title=&quot;IFrame content&quot;&gt;&lt;/iframe&gt;
&lt;/div&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; Code splitting can significantly improve an app&#39;s initial load time, but it comes at the cost of slowing down subsequent navigation. In the &lt;a href=&quot;https://web.dev/route-preloading-in-angular&quot;&gt;next post&lt;/a&gt; on route preloading you&#39;ll see how to work around this problem! &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/route-level-code-splitting-in-angular/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can shrink the bundle size of your Angular applications by applying route-level code splitting:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use the Angular CLI lazy-loaded module generator to automatically scaffold a dynamically loaded route.&lt;/li&gt;
&lt;li&gt;Add a loading indicator when the user navigates to a lazy route to show there&#39;s an ongoing action.&lt;/li&gt;
&lt;/ol&gt;
</content>
    <author>
      <name>Minko Gechev</name>
    </author>
  </entry>
</feed>
