{"componentChunkName":"component---src-templates-blog-post-js","path":"/angular-polyfill-strategies/","result":{"data":{"site":{"siteMetadata":{"title":"Fabrizio Fortunato","author":"Fabrizio Fortunato","siteUrl":"https://izifortune.com"}},"markdownRemark":{"id":"94ab258b-0ef0-5167-9077-3df34942c426","excerpt":"Cross browser compatibility is a big part of modern web development. While the majority of browsers are now aligning to the new web standards, cross browser…","html":"<p>Cross browser compatibility is a big part of modern web development. While the majority of browsers are now aligning to the new web standards, cross browser issues still occur for different reasons. Sometimes browsers have bugs, different level of support for a new technology. <em>Angular</em> supports all the most recent browsers but supporting all this variety of browsers it’s challenging especially where there are lacks of support for modern technologies. This is why the <em>Angular</em> team <a href=\"https://angular.io/guide/browser-support\">recommends</a> to load polyfills depending on your targets. The polyfill provides a functionality expected to be natively available.</p>\n<p>An <em>Angular</em> application created with the <em>angular-cli</em> contain the file <code class=\"language-text\">src/polyfills.ts</code>. The file highlight the different modules that might be needed for a specific browser in order to work properly. While creating a web application, especially a public facing one, it is necessary to deal with cross browser compatibility. A user might come to your web app using an older browser or an older version of a browser and you shouldn’t force them to upgrade. Depending on the project audience it is necessary to load the polyfills needed.</p>\n<p>In this post, I want to explore different approaches to load polyfills on an Angular application. Starting from a very simple scenario where we load all the possible modules to more advanced ones. The polyfills are often a neglected part of an <em>Angular</em> application resulting in a performance loss for your web application and users.</p>\n<h3>Bundle them all</h3>\n<p>In our first case, we are just blindly uncommenting all the imports statements in our polyfills files. This is a very simple case and I imagine for a lot of developers that are starting an <em>Angular</em> project, this is the easiest way to get your application working with no extra effort, except for your users.</p>\n<div class=\"gatsby-highlight\" data-language=\"typescript\"><pre class=\"language-typescript\"><code class=\"language-typescript\"><span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/symbol'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/object'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/function'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/parse-int'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/parse-float'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/number'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/math'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/string'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/date'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/array'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/regexp'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/map'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/weak-map'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/set'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/array'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'classlist.js'</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// Run `npm install --save classlist.js`.</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/reflect'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'web-animations-js'</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// Run `npm install --save web-animations-js`.</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'zone.js/dist/zone'</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// Included with Angular CLI.</span></code></pre></div>\n<p>All the browsers, even the ones which don’t need polyfills, are paying the price of the older browser in your list of supported ones. So every user needs to download the generated file in its entirety. If we look at the generated polyfill bundle size, this is double the space that a common utility library such as <a href=\"https://ramdajs\">ramda</a> or <a href=\"https://lodash.com/\">lodash</a> occupies without using any tree-shaking on them.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto;  max-width: 590px;\"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/dist/static/597df7120e464565d1e20d42331cd4a1/7dc98/polyfills-ramda-lodash.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 62.16216216216216%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsSAAALEgHS3X78AAABcElEQVQoz42Sv0/CQBTH+285uiiDg5hoNDEmsujmooOjMcZBIotR40IMLA4ODm4SJeggDg4QGmMA4eRXMKVAr+X67od3bQcVG/3m2ty96+d93/WdxjyJEFHGXeD+nLlgVJFpmhhjSqmktHBMva+fYedyFIQ45yPHx/yAxj19xeRKDh8+z7krJ3aYgQZKrvc1Z0EmmYsDVRnT9yR2ZnumPz0UPJ5vYPNyhwEVHux6cIizn67T58ksMbGa35Vg6ci2idpIBc6hZUsLKCI6uWehLsgKbwoQPcR4pA6dypHYqSWAcMbGqhaaDEpAb7CZOG4P1X6mCHMJ7Dun82J5u9DaXKfGR/Azv8HeUm/yyH6/dJwUSM+8itn4wOpZsl/pJ7G48ViZnoB2MwxmepNFD3oPUxFxe5VtiIXd+staTNSKFwWxupWvzkdIu/ULLB/ZKtshqDPo1urEGloOvL0bRqXsYquPoYa6JqoTR12Pv1v1f30COaqgOyDHcNoAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"polyfills ramda lodash\"\n        title=\"polyfills ramda lodash\"\n        src=\"/dist/static/597df7120e464565d1e20d42331cd4a1/102e5/polyfills-ramda-lodash.png\"\n        srcset=\"/dist/static/597df7120e464565d1e20d42331cd4a1/83276/polyfills-ramda-lodash.png 148w,\n/dist/static/597df7120e464565d1e20d42331cd4a1/ba02f/polyfills-ramda-lodash.png 295w,\n/dist/static/597df7120e464565d1e20d42331cd4a1/102e5/polyfills-ramda-lodash.png 590w,\n/dist/static/597df7120e464565d1e20d42331cd4a1/74549/polyfills-ramda-lodash.png 885w,\n/dist/static/597df7120e464565d1e20d42331cd4a1/7213b/polyfills-ramda-lodash.png 1180w,\n/dist/static/597df7120e464565d1e20d42331cd4a1/7dc98/polyfills-ramda-lodash.png 1200w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<h3>IE aside</h3>\n<p>As you can imagine this is not an ideal solution and it is impacting all your users with no discrimination. On my research to improve the previous solution I stumble across what is currently used at <a href=\"https://angular.io\">angular.io</a>. The website serves an additional file <code class=\"language-text\">ie-polyfill</code> only to IE11/10/9 browser and a smaller polyfill for all the rest. The solution implemented is simple and effective and it consists of pre-generating a bundle for IE and loading it in a <em>script</em> tag with always present in the index adding <code class=\"language-text\">nomodule</code> attribute. </p>\n<p>Create the following file <code class=\"language-text\">src/ie-polyfills.js</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"tyepscript\"><pre class=\"language-tyepscript\"><code class=\"language-tyepscript\">/** IE9, IE10 and IE11 requires all of the following polyfills. **/\nimport &#39;core-js/es6/symbol&#39;;\nimport &#39;core-js/es6/object&#39;;\nimport &#39;core-js/es6/function&#39;;\nimport &#39;core-js/es6/parse-int&#39;;\nimport &#39;core-js/es6/parse-float&#39;;\nimport &#39;core-js/es6/number&#39;;\nimport &#39;core-js/es6/math&#39;;\nimport &#39;core-js/es6/string&#39;;\nimport &#39;core-js/es6/date&#39;;\nimport &#39;core-js/es6/array&#39;;\nimport &#39;core-js/es6/regexp&#39;;\nimport &#39;core-js/es6/map&#39;;\nimport &#39;core-js/es6/set&#39;;\nimport &#39;classlist.js&#39;;\nimport &#39;web-animations-js&#39;;</code></pre></div>\n<p>Leaving only the following inside <code class=\"language-text\">src/polyfill.ts</code></p>\n<div class=\"gatsby-highlight\" data-language=\"typescript\"><pre class=\"language-typescript\"><code class=\"language-typescript\"><span class=\"token keyword\">import</span> <span class=\"token string\">'zone.js/dist/zone'</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// Included with Angular CLI.</span></code></pre></div>\n<p>—UPDATE—\nTo generate the <em>ie-polyfills</em> first we will need to create a webpack configuration in <code class=\"language-text\">webpack-polyfill-config.js</code></p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> UglifyJsPlugin <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'uglifyjs-webpack-plugin'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nmodule<span class=\"token punctuation\">.</span>exports <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n  mode<span class=\"token operator\">:</span> <span class=\"token string\">'production'</span><span class=\"token punctuation\">,</span>\n  optimization<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    minimizer<span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">UglifyJsPlugin</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n      uglifyOptions<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        warnings<span class=\"token operator\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span>\n        parse<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n        compress<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n        mangle<span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// Note `mangle.properties` is `false` by default.</span>\n        output<span class=\"token operator\">:</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span>\n        toplevel<span class=\"token operator\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span>\n        nameCache<span class=\"token operator\">:</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span>\n        ie8<span class=\"token operator\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span>\n        keep_fnames<span class=\"token operator\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>—ENDUPDATE—</p>\n<p>Then just add the following command inside the <em>script</em> section in the <code class=\"language-text\">package.json</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"json\"><pre class=\"language-json\"><code class=\"language-json\"><span class=\"token property\">\"build-ie-polyfills\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"webpack-cli src/ie-polyfills.js -o src/generated/ie-polyfills.min.js --optimize-minimize -c webpack-polyfill.config.js\"</span><span class=\"token punctuation\">,</span>\n<span class=\"token property\">\"postbuild\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"cp -p src/generated/ie-polyfills.min.js dist/generated\"</span></code></pre></div>\n<p>And finally, add the <em>script</em> tag inside the head in <code class=\"language-text\">src/index.html</code>:  </p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>script</span> <span class=\"token attr-name\">nomodule</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span><span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>generated/ie-polyfills.min.js<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token script\"></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>script</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<p>The <code class=\"language-text\">nomodule</code> attribute is a boolean attribute that prevents a script from being executed in user agents that support module scripts. Only browsers that do not support modules like IE11/10/9, will download the bigger bundle while the rest of the browsers will ignore it and just download the smaller file.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto;  max-width: 590px;\"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/dist/static/286b09435344563cb154f073faf3e6c0/7dc98/polyfill-strategies.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 62.16216216216216%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsSAAALEgHS3X78AAABaklEQVQoz52SS0vDQBDH89UEldIi2CqCJ+ldBE9ePAkqWkERrx48iHgTD4IgVvGBBwNWawvSmliTJn2Z2GSbZh8Zs4koalvFYXdhZvc385/dFRhjnj88cInnrz2MYfIiPZumiRCilPqgEALFCpvacho2d/wI65jFT952QiwMCJQf9HIKG1y0dfMd/qMJLiYAJKfS6LKtGTxlQac7ly6mXlDr0zrAocI8h1HZ4M7hLYksoTYJ+uzWwnc4hbRA9vE9GV1DbgD37kAghHLZCpetVtt+saMsSawiB/PtG5nuixj4c3QQLrDgwvIaRBdMcXIaMufpR4ivvDZVHQBvnuDxDfSbbA0i8+ZFXz+k99IqDM2WcvEYSJltEZLrDVYuAaXdYJYvs3jKuBoegbODUwXG5uS72AA8iLtZSM5cP00k3IoOP55R8CchuOW4ag0ZioKR1USupDTqsoRbqGbYcqlaLxZsy/r4G1/gf9sb2Lmem0gvLkMAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"polyfill strategies\"\n        title=\"polyfill strategies\"\n        src=\"/dist/static/286b09435344563cb154f073faf3e6c0/102e5/polyfill-strategies.png\"\n        srcset=\"/dist/static/286b09435344563cb154f073faf3e6c0/83276/polyfill-strategies.png 148w,\n/dist/static/286b09435344563cb154f073faf3e6c0/ba02f/polyfill-strategies.png 295w,\n/dist/static/286b09435344563cb154f073faf3e6c0/102e5/polyfill-strategies.png 590w,\n/dist/static/286b09435344563cb154f073faf3e6c0/74549/polyfill-strategies.png 885w,\n/dist/static/286b09435344563cb154f073faf3e6c0/7213b/polyfill-strategies.png 1180w,\n/dist/static/286b09435344563cb154f073faf3e6c0/7dc98/polyfill-strategies.png 1200w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<p>That’s almost a 60% improvement over the initial, <em>bundle them all</em>, solution proposed. It can be easily integrated in any application and it doesn’t involve any complex change or infrastructure support. There is only one additional file served by your application. Here’s a link to a stackblitz application already configured for the occasion <a href=\"https://stackblitz.com/edit/angular-ahwqb6\">here</a>.</p>\n<h3>Serverless service</h3>\n<p>The previous solution its great and I really encourage to test it out in your project to get an easy performance boost. There are few issues that cannot be ignored: the older browsers will have to perform an additional request to fetch two polyfills. Also using <code class=\"language-text\">nomodule</code> can only differentiate between browsers that support or not module. There are scenarios where you need to load a polyfill only for a specific browser. In one of our web application, we needed to load <code class=\"language-text\">core-js/es7/object</code> specifically for IOS 9 for example.</p>\n<p>A more advanced solution is to dynamically serve the polyfills by detecting the browser request. The user-agent header can be used to detect the browser making the request.\nA popular service used widely by the web development community is <a href=\"https://polyfill.io\">polyfill.io</a>. The service created by Jonathan Neal, does exactly what describe earlier. Unfortunately, <em>polyfill.io</em> cannot be used for <em>Angular</em> applications due to the changes that it performs on global objects</p>\n<p>The solution provided by <em>polyfill.io</em> it’s very promising and reduces the total number of calls even for the oldest browser in the group. Serverless can recreate a similar solution to <em>polyfill.io</em> which can be easy to set up, maintain and also working with <em>Angular</em> applications.</p>\n<p><a href=\"https://serverless.com\">Serverless</a> framework is an open-source CLI for building and deploying serverless applications. <em>Serverless</em> provides basically a layer of abstraction on top of different cloud providers such as <em>AWS</em>, <em>Google cloud</em> or <em>Azure</em>.\nLet’s start by downloading and installing the <em>serverless-cli</em> globally.</p>\n<p>Prerequisite for this section are: an <em>AWS</em> account and the <em>aws-cli</em> installed on your machine.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> i -g serverless</code></pre></div>\n<p>Now that the <em>serverless-cli</em> is installed globally, we can use it to create the first project based on a nodejs template.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">serverless create --template aws-nodejs --path angular-polyfill <span class=\"token operator\">&amp;&amp;</span> <span class=\"token builtin class-name\">cd</span> angular-polyfill <span class=\"token operator\">&amp;&amp;</span> <span class=\"token function\">npm</span> init</code></pre></div>\n<p>The cli creates two different files inside the project: <code class=\"language-text\">serverless.yml</code> that specify the infrastructure configuration of the service. <code class=\"language-text\">handler.js</code> which contains the function, this is a lambda function which will be executed in a managed <em>AWS</em> infrastructure.</p>\n<p>Before going into serverless specifics, in order to generate the different polyfills bundles, we are going to use <em>webpack</em> directly using the command line interface. To reduce the size we will also configure the <em>UglifyJsPlugin</em> which will take care to perform the necessary optimisations. Start by adding some dependencies</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> i --save-dev core-js web-animations-js classlist.js webpack zone.js webpack-cli uglifyjs-webpack-plugin</code></pre></div>\n<p>Create a simple <em>webpack</em> configuration in <code class=\"language-text\">webpack.config.js</code> and the <em>javascript</em> files with the different polyfills imports</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// webpack.config.js</span>\n<span class=\"token keyword\">const</span> UglifyJsPlugin <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'uglifyjs-webpack-plugin'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nmodule<span class=\"token punctuation\">.</span>exports <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n  mode<span class=\"token operator\">:</span> <span class=\"token string\">'production'</span><span class=\"token punctuation\">,</span>\n  optimization<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    minimizer<span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">UglifyJsPlugin</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n      uglifyOptions<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        warnings<span class=\"token operator\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span>\n        parse<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n        compress<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n        mangle<span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// Note `mangle.properties` is `false` by default.</span>\n        output<span class=\"token operator\">:</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span>\n        toplevel<span class=\"token operator\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span>\n        nameCache<span class=\"token operator\">:</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span>\n        ie8<span class=\"token operator\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span>\n        keep_fnames<span class=\"token operator\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//polyfills.js</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es7/reflect'</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Used in JIT - remove if you use only AOT</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'zone.js/dist/zone'</span><span class=\"token punctuation\">;</span></code></pre></div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//ie-polyfills.js</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/symbol'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/object'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/function'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/parse-int'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/parse-float'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/number'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/math'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/string'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/date'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/array'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/regexp'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/map'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es6/set'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'classlist.js'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'web-animations-js'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">import</span> <span class=\"token string\">'core-js/es7/reflect'</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Used in JIT - remove if you use only AOT</span>\n<span class=\"token keyword\">import</span> <span class=\"token string\">'zone.js/dist/zone'</span><span class=\"token punctuation\">;</span>  </code></pre></div>\n<p>And last we add the scripts in our <code class=\"language-text\">package.json</code></p>\n<div class=\"gatsby-highlight\" data-language=\"json\"><pre class=\"language-json\"><code class=\"language-json\"><span class=\"token property\">\"build-ie-polyfills\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"webpack-cli polyfills.js ie-polyfills.js  -o ./generated/ie-polyfills.min.js --mode production --optimize-minimize -c webpack.config.js\"</span><span class=\"token punctuation\">,</span>\n<span class=\"token property\">\"build-polyfills\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"webpack-cli polyfills.js -o ./generated/polyfills.min.js --mode production --optimize-minimize -c webpack.config.js\"</span></code></pre></div>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> run build-ie-polyfills <span class=\"token operator\">&amp;&amp;</span> <span class=\"token function\">npm</span> run build-polyfills</code></pre></div>\n<p>Running the two commands generate two different polyfills files inside the <code class=\"language-text\">generated</code> folder to be used inside our serverless function. <em>Serverless</em> framework needs to include the generated files in the function created. Inside <code class=\"language-text\">serverless.yml</code> specify:</p>\n<div class=\"gatsby-highlight\" data-language=\"yaml\"><pre class=\"language-yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">package</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">include</span><span class=\"token punctuation\">:</span>\n    <span class=\"token punctuation\">-</span> generated/polyfill.min.js\n    <span class=\"token punctuation\">-</span> generated/ie<span class=\"token punctuation\">-</span>polyfill.min.js\n  <span class=\"token key atrule\">exclude</span><span class=\"token punctuation\">:</span>\n    <span class=\"token punctuation\">-</span> ie<span class=\"token punctuation\">-</span>polyfills.js\n    <span class=\"token punctuation\">-</span> polyfills.js</code></pre></div>\n<p>It is time to open <code class=\"language-text\">handler.js</code> and add the logic to serve a different polyfill based upon the <em>user agent</em> of the request. The idea is to detect the <em>user agent</em> and then based upon such information serve one or the other polyfill. Import a utility library which parses the <em>user agent</em> string with high accuracy by using hand-tuned dedicated regular expressions for browser matching.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token function\">npm</span> i --save useragent</code></pre></div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//handler.js</span>\n<span class=\"token string\">'use strict'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> useragent <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'useragent'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> util <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'util'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> fs <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'fs'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> readFile <span class=\"token operator\">=</span> util<span class=\"token punctuation\">.</span><span class=\"token function\">promisify</span><span class=\"token punctuation\">(</span>fs<span class=\"token punctuation\">.</span>readFile<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> path <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'path'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">getPolyFillName</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">browser</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">switch</span> <span class=\"token punctuation\">(</span>browser<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">case</span> <span class=\"token string\">'ie'</span><span class=\"token operator\">:</span>\n      <span class=\"token keyword\">return</span> path<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span>__dirname<span class=\"token punctuation\">,</span> <span class=\"token string\">'/generated/ie-polyfills.min.js'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">default</span><span class=\"token operator\">:</span>\n      <span class=\"token keyword\">return</span> path<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span>__dirname<span class=\"token punctuation\">,</span> <span class=\"token string\">'/generated/polyfills.min.js'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\nmodule<span class=\"token punctuation\">.</span>exports<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">polyfill</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">event<span class=\"token punctuation\">,</span> context</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> ua <span class=\"token operator\">=</span> useragent<span class=\"token punctuation\">.</span><span class=\"token function\">parse</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">[</span><span class=\"token string\">'user-agent'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>ua<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> body <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">readFile</span><span class=\"token punctuation\">(</span><span class=\"token function\">getPolyFillName</span><span class=\"token punctuation\">(</span>ua<span class=\"token punctuation\">.</span>family<span class=\"token punctuation\">.</span><span class=\"token function\">toLowerCase</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'utf8'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">{</span>\n    statusCode<span class=\"token operator\">:</span> <span class=\"token number\">200</span><span class=\"token punctuation\">,</span>\n    body<span class=\"token punctuation\">,</span>\n    headers<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token string\">'Content-Type'</span><span class=\"token operator\">:</span> <span class=\"token string\">'application/javascript'</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string\">'X-Detected-UA'</span><span class=\"token operator\">:</span> ua<span class=\"token punctuation\">.</span>family<span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>The serverless function needs an endpoint for our browser to reach it. While working with <em>AWS</em> we can attach a lambda to an <a href=\"https://aws.amazon.com/api-gateway/\">API Gateway</a> and the latter will provide the integration from the function to the <em>REST</em> endpoint. <em>Serverless</em> simplify the creation of all the resources needed by simply adding <em>events</em> to the function inside <code class=\"language-text\">serverless.yml</code></p>\n<div class=\"gatsby-highlight\" data-language=\"yaml\"><pre class=\"language-yaml\"><code class=\"language-yaml\">  <span class=\"token key atrule\">polyfill</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">handler</span><span class=\"token punctuation\">:</span> handler.polyfill\n    <span class=\"token key atrule\">events</span><span class=\"token punctuation\">:</span>\n       <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">http</span><span class=\"token punctuation\">:</span>\n           <span class=\"token key atrule\">method</span><span class=\"token punctuation\">:</span> get\n           <span class=\"token key atrule\">path</span><span class=\"token punctuation\">:</span> /polyfill</code></pre></div>\n<p>Now we are ready to deploy our function</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">sls deploy</code></pre></div>\n<p>Serverless outputs at the end of the creation process a URL that point to your lambda.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto;  max-width: 590px;\"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/dist/static/ee4a1416b12b4b946f5e9407a4ffb504/57679/serverless-output.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 36.486486486486484%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsSAAALEgHS3X78AAAA70lEQVQY042P3W6EIBCFeY1WFxUFRAFR6r8RsqZJm9iL3uz7P0pnS5v0qm1yMvkYcmbOoNs5vl67Z9+/n/7tZb26STZtwcoYp5ck+13o2M3cK2VsWemcVWnOcspxSv5lvp3Dsenduc35aV5NZ6taSW2ynP7pR/tm/T5IKeIkS1KSkgJnJMlycEaXJNSgnxyEtrlblyclS7gTAlNeggJDDUAKBkAKSrmAX3h+gkDH4dd1GcdBqoaJulaNNi3EBviWrqSGDhd1a3u4C5pNa7Xp0DK1bht6q2ESjL+v5eK+lnJWCrjiMcaQ8KtG+CHCwEEf6z5A/PASOxEAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"serverless output\"\n        title=\"serverless output\"\n        src=\"/dist/static/ee4a1416b12b4b946f5e9407a4ffb504/102e5/serverless-output.png\"\n        srcset=\"/dist/static/ee4a1416b12b4b946f5e9407a4ffb504/83276/serverless-output.png 148w,\n/dist/static/ee4a1416b12b4b946f5e9407a4ffb504/ba02f/serverless-output.png 295w,\n/dist/static/ee4a1416b12b4b946f5e9407a4ffb504/102e5/serverless-output.png 590w,\n/dist/static/ee4a1416b12b4b946f5e9407a4ffb504/74549/serverless-output.png 885w,\n/dist/static/ee4a1416b12b4b946f5e9407a4ffb504/7213b/serverless-output.png 1180w,\n/dist/static/ee4a1416b12b4b946f5e9407a4ffb504/57679/serverless-output.png 1254w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<p>To test that everything is working by pasting the URL in your browser and the service should return you the polyfill bundle targeted for your browser. </p>\n<p>We can now easily modify our Angular application to download the polyfills directly from the service URL and remove polyfills bundling from it.</p>\n<p>This is a very simple setup to showcase the power of <em>serverless</em>, depending on your website traffic there are different ways to enhance it, if you are interested let me know in the comments below.</p>\n<p>Spending time deciding the polyfills that should be included is often omitted, penalising everyone for the “sin” of a few. The solutions explored hopefully will help you improve your website’s app experience for your users.</p>","frontmatter":{"title":"Angular polyfill strategies","date":"November 12, 2018","description":"Cross browser compatibility is a big part of modern web development. We will explore different approaches to load polyfills on an Angular application.","socialImage":{"childImageSharp":{"fixed":{"src":"/dist/static/8a4f07db6b81407d179bd8ddc7c779c7/048fd/angular-polyfill-strategies.png"}}},"image":{"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsSAAALEgHS3X78AAAA40lEQVQY02PQLT+OiWxydxV69i2Sj6yxLHdPXqtXdgyrMgZkjn7ZUbWaswEJKy+yWz1n0rvHZXSSQf04g065ba16zVm9sqMENKvWnA2KW3GP0fAOg87zqskHxezPMsjXWJWr1F3Qx68Z6DzNqlMO2TvOsFo9EnN627/kanTVKQb5dO8+5fqL+qV4NeuWH9OpOGFYeuQMj/UrQatLUs5njMIuMChHBc8A2UxIM8Ty09k+k07yOtxjUNnLqNVsVGBSuB9oqC5GsDFghqFe+TGV2nOWhfsqnFv9Elao1p4H6SzHEuAAD+q+fvifXcUAAAAASUVORK5CYII=","aspectRatio":2.830508474576271,"src":"/dist/static/5e61bb4d1086dfd226439370d1873d85/a5924/angular-polyfill-strategies2.png","srcSet":"/dist/static/5e61bb4d1086dfd226439370d1873d85/17cc0/angular-polyfill-strategies2.png 167w,\n/dist/static/5e61bb4d1086dfd226439370d1873d85/f7869/angular-polyfill-strategies2.png 333w,\n/dist/static/5e61bb4d1086dfd226439370d1873d85/a5924/angular-polyfill-strategies2.png 666w,\n/dist/static/5e61bb4d1086dfd226439370d1873d85/4f774/angular-polyfill-strategies2.png 674w","sizes":"(max-width: 666px) 100vw, 666px"}}}}}},"pageContext":{"slug":"/angular-polyfill-strategies/","previous":{"fields":{"slug":"/snapshot-testing-angular-applications/"},"frontmatter":{"title":"Snapshot testing Angular applications"}},"next":{"fields":{"slug":"/theming-angular-at-ryanair/"},"frontmatter":{"title":"Theming Angular at Ryanair"}}}}}