{"id":212,"date":"2019-05-01T05:00:41","date_gmt":"2019-05-01T03:00:41","guid":{"rendered":"https:\/\/www.angulararchitects.io\/?post_type=post&amp;p=212"},"modified":"2019-05-01T05:00:41","modified_gmt":"2019-05-01T03:00:41","slug":"your-options-for-building-angular-elements","status":"publish","type":"post","link":"https:\/\/www.angulararchitects.io\/en\/blog\/your-options-for-building-angular-elements\/","title":{"rendered":"Your options for building Angular Elements"},"content":{"rendered":"<style>\n<!--\n\n    .article pre {\n        font-size:16px;\nfont-family: \"Courier New\", Courier, monospace;\ncolor: black!important;\n     }\n\n    .article p img {\n        margin-top: 0px;\n        margin-bottom: 0px;\n     }\n\n    .article h2 {\n      font-size: 30px;\n      line-height: 45px;\n      padding-top:20px!important;\n    }\n\n    .article h3 {\n      font-size: 25px;\n      line-height: 35px;\n      padding-top:15px!important;\n    }\n\n    .article p, .article ul li, .article td, .article th, .article blockquote.info p {\n       line-height:30px!important;\n       font-size:20px!important;\n     }\n\n     .article img.img {\n         margin-top:10px!important;\n         margin-bottom: 10px!important;\n     }\n\n     .article pre {\n        margin-top:20px!important;\n        margin-bottom:20px!important;\n     }\n\n    .article h4 {\n       font-size:25px;\n       line-height: 35px;\n       padding-top:15px;\n       font-weight: bold;\n    }\n\n    .article table {\n       margin-top: 30px!important;\n    }\n\n    .article li {\n    font-size: 16px!important;\n    }\n\n    .article td, .article th {\n        padding-right:20px;\n        padding-bottom:20px;\n        font-size: 16px!important;\n    }\n    .article th {\n        font-weight:bold;\n        text-align: left\n    }\n    .article li a {\n        text-decoration: underline;\n    }\n\n    .language-typescript {\n    color: black;\n    }\n-->\n    <\/style>\n<div class=\"article\">\n<hr>\n<div style=\"font-size:14px\">\n<b style=\"font-weight: bold\">This blog post is part of an article series.<\/b><\/p>\n<ul class=\"toc\">\n<li><a href=\"http:\/\/www1.angulararchitects.io.dedi1415.your-server.de\/post\/2018\/07\/13\/angular-elements-part-i-a-dynamic-dashboard-in-four-steps-with-web-components.aspx\">Angular Elements, Part I: A Dynamic Dashboard In Four Steps With Web Components<\/a><\/li>\n<li><a href=\"http:\/\/www1.angulararchitects.io.dedi1415.your-server.de\/post\/2018\/07\/29\/angular-elements-part-ii-lazy-and-external-web-components.aspx\">Angular Elements, Part II: Lazy And External Web Components<\/a><\/li>\n<li><a href=\"http:\/\/www1.angulararchitects.io.dedi1415.your-server.de\/post\/2018\/07\/06\/angular-elements-without-zone-js.aspx\">Angular Elements, Part III: Angular Elements without Zone.js<\/a><\/li>\n<li><a href=\"http:\/\/www1.angulararchitects.io.dedi1415.your-server.de\/post\/2018\/10\/31\/content-projection-with-slots-in-angular-elements-7.aspx\" target=\"_blank\" rel=\"noopener\">Angular Elements, Part IV:&nbsp;Content Projection with Slots in Angular Elements (&gt;=7)<\/a><\/li>\n<li><a href=\"http:\/\/www1.angulararchitects.io.dedi1415.your-server.de\/post\/2019\/01\/27\/building-angular-elements-with-the-cli.aspx\">Angular Elements, Part V: Your Options For Building Angular Elements With The CLI<\/a><\/li>\n<\/ul>\n<\/div>\n<hr>\n<p>&nbsp;<\/p>\n<p>In this article you will learn:<\/p>\n<ul>\n<li>? How to provide a single bundle for your Angular Elements<\/li>\n<li>? How to use polyfills for legacy browsers<\/li>\n<li>? How Ivy can help with bundle sizes (once it\u2019s released) and where it cannot<\/li>\n<li>? How differential serving can help (not only) with Angular Elements<\/li>\n<li>? How to share dependencies between separately compiled Angular Elements<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/manfredsteyer\/build-elements\">Source Code<\/a><\/p>\n<p>Currently, Angular Elements officially supports exposing Angular Components as Web Components -- or more precisely: as Custom Elements -- <strong>within<\/strong> Angular projects. Upcoming versions will very likely also support exporting Web Components which can be used with other frameworks or VanillaJS. I'm using the term <em>external<\/em> web component for referring to this. Another term is standalone (web) component.<\/p>\n<p>In this article, I provide several strategies you can use to provide external web components already today. Some of them will definitely benefit from the introduction of Ivy and some of them address different aspects.<\/p>\n<p>One more time, I want to thank <a href=\"https:\/\/twitter.com\/robwormald\">Rob Wormald<\/a> -- the father of and master mind behind Angular Elements -- for discussions that led to some of the solutions presented here.<\/p>\n<h2 id=\"initial-situation\">Initial Situation<\/h2>\n<p>The example used here is a variation of the dashboard tile component from my <a href=\"http:\/\/www1.angulararchitects.io.dedi1415.your-server.de\/post\/2018\/07\/13\/angular-elements-part-i-a-dynamic-dashboard-in-four-steps-with-web-components.aspx\">introduction to Angular Elements<\/a>:<\/p>\n<p>It can be found <a href=\"https:\/\/github.com\/manfredsteyer\/build-elements\">here<\/a> and consists of a CLI workspace with two projects. One of them called <code>dashboard-tile<\/code> exposes a simple dashboard tile as an external component:<\/p>\n<p><img decoding=\"async\" class=\"img\" src=\"http:\/\/www1.angulararchitects.io.dedi1415.your-server.de\/wp-content\/uploads\/2017\/09\/build-02.png\" alt=\"External Web Component\"><\/p>\n<p>The code behind it is quite simple:<\/p>\n<pre class=\"language-typescript\"><div><span class=\"hljs-meta\">@Component<\/span>({\n  <span class=\"hljs-comment\">\/\/ selector: 'app-external-dashboard-tile',<\/span>\n  templateUrl: <span class=\"hljs-string\">'.\/external-dashboard-tile.component.html'<\/span>,\n  styleUrls: [<span class=\"hljs-string\">'.\/external-dashboard-tile.component.css'<\/span>]\n})\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> ExternalDashboardTileComponent <span class=\"hljs-keyword\">implements<\/span> OnInit {\n\n  <span class=\"hljs-meta\">@Input<\/span>() src: <span class=\"hljs-built_in\">number<\/span> = <span class=\"hljs-number\">1<\/span>;\n\n  a: <span class=\"hljs-built_in\">number<\/span>;\n  b: <span class=\"hljs-built_in\">number<\/span>;\n  c: <span class=\"hljs-built_in\">number<\/span>;\n\n  <span class=\"hljs-keyword\">constructor<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">private<\/span> http: HttpClient<\/span>) {\n  }\n\n  ngOnInit(): <span class=\"hljs-built_in\">void<\/span> {\n    <span class=\"hljs-keyword\">this<\/span>.load();\n  }\n\n  load() {\n    <span class=\"hljs-keyword\">this<\/span>.http.get(<span class=\"hljs-string\"><code>\/assets\/stats-&lt;span class=&quot;hljs-subst&quot;&gt;${this.src}&lt;\/span&gt;.json<\/code><\/span>).subscribe(\n      <span class=\"hljs-function\"><span class=\"hljs-params\">data<\/span> =&gt;<\/span> {\n        <span class=\"hljs-keyword\">this<\/span>.a = data[<span class=\"hljs-string\">'a'<\/span>];\n        <span class=\"hljs-keyword\">this<\/span>.b = data[<span class=\"hljs-string\">'b'<\/span>];\n        <span class=\"hljs-keyword\">this<\/span>.c = data[<span class=\"hljs-string\">'c'<\/span>];\n      }\n    );\n  }\n\n  more() {\n    <span class=\"hljs-keyword\">this<\/span>.src++;\n    <span class=\"hljs-keyword\">if<\/span> (<span class=\"hljs-keyword\">this<\/span>.src &gt; <span class=\"hljs-number\">3<\/span>) {\n      <span class=\"hljs-keyword\">this<\/span>.src = <span class=\"hljs-number\">1<\/span>;\n    }\n    <span class=\"hljs-keyword\">this<\/span>.load();\n  }\n\n}\n<\/div><\/pre>\n<p>In order to provide this component as a custom element when the Angular application starts up, the respective code is placed in the <code>AppModule<\/code>'s <code>ngDoBootstrap<\/code> method:<\/p>\n<pre class=\"language-typescript\"><div><span class=\"hljs-meta\">@NgModule<\/span>({\n   imports: [\n      HttpClientModule,\n      BrowserModule\n   ],\n   declarations: [\n      ExternalDashboardTileComponent\n   ],\n   bootstrap: [],\n   entryComponents: [\n      ExternalDashboardTileComponent\n   ]\n})\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> AppModule { \n    <span class=\"hljs-keyword\">constructor<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">private<\/span> injector: Injector<\/span>) {\n    }\n\n    ngDoBootstrap() {\n        <span class=\"hljs-keyword\">const<\/span> externalTileCE = createCustomElement(ExternalDashboardTileComponent, { injector: <span class=\"hljs-keyword\">this<\/span>.injector });\n        customElements.define(<span class=\"hljs-string\">'external-dashboard-tile'<\/span>, externalTileCE);\n    }\n\n}\n<\/div><\/pre>\n<p>Here, <code>ngDoBootstrap<\/code> is needed because the application does not have a bootstrap component. This is because I don't want to bootstrap an ordinary Angular component but just register a custom element with the browser.<\/p>\n<p>In theory, you should be able to call the web component directly within the <code>index.html<\/code> after exposing it that way.<\/p>\n<pre class=\"language-html\"><div><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">external-dashboard-tile<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"1\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">external-dashboard-tile<\/span>&gt;<\/span>\n<\/div><\/pre>\n<p>In practice, you get the following error when trying this out with the starter branch of the provided source code:<\/p>\n<blockquote class=\"info\"><p>\nFailed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function.\n<\/p><\/blockquote>\n<p><img decoding=\"async\" class=\"img\" src=\"http:\/\/www1.angulararchitects.io.dedi1415.your-server.de\/wp-content\/uploads\/2017\/09\/build-01.png\" alt=\"\"><\/p>\n<p>This error occors at least, when using EcmaScript 5 as a compilation target in order to support older browsers like Internet Explorer 11.This is because Custom Elements are to be used with EcmaScript 2015 and above by definition.<\/p>\n<p>Hence, we need a polyfill for newer browsers which expect EcmaScript 2015+ Custom Elements and another polyfill for older browsers like Internet Explorer 11.<\/p>\n<blockquote class=\"info\"><p>\nDifferential loading, introduced with Angular CLI 8, allows to create EcmaScript 5 and EcmaScript 2015 bundles side by side. In one of the next sections, I'll provide more information about this.\n<\/p><\/blockquote>\n<h2 id=\"polyfills\">Polyfills<\/h2>\n<p>In order to also support old browsers, I've decided to go with the polyfills in the <code>@webcomponents\/webcomponentsjs<\/code> package. To load them, I register them as scripts within <code>angular.json<\/code>:<\/p>\n<pre class=\"language-json\"><div>[...],\n<span class=\"hljs-string\">\"scripts\"<\/span>: [\n  {\n    <span class=\"hljs-attr\">\"bundleName\"<\/span>: <span class=\"hljs-string\">\"polyfill-webcomp-es5\"<\/span>,\n    <span class=\"hljs-attr\">\"input\"<\/span>: <span class=\"hljs-string\">\"node_modules\/@webcomponents\/webcomponentsjs\/custom-elements-es5-adapter.js\"<\/span>\n  },\n  {\n    <span class=\"hljs-attr\">\"bundleName\"<\/span>: <span class=\"hljs-string\">\"polyfill-webcomp\"<\/span>,\n    <span class=\"hljs-attr\">\"input\"<\/span>: <span class=\"hljs-string\">\"node_modules\/@webcomponents\/webcomponentsjs\/bundles\/webcomponents-sd-ce-pf.js\"<\/span>\n  }\n],\n[...]\n<\/div><\/pre>\n<p>If you only compile to <code>es2015<\/code>+, you can omit the first script.<\/p>\n<p>When building, this leads to two further bundles: <code>polyfill-webcomp-es5.js<\/code> and <code>polyfill-webcomp<\/code>.<\/p>\n<h2 id=\"adding-polyfills-automatically\">Adding Polyfills Automatically<\/h2>\n<p>To automate the cumbersome task of adding polyfills, I've written a schematic which is part of my community project <code>ngx-build-plus<\/code>. To install it, use <code>ng add<\/code>:<\/p>\n<pre><div>ng add ngx-build-plus --project dashboard-tile \n<\/div><\/pre>\n<p>After that, you can install the polyfills with an included schematic:<\/p>\n<pre><div>ng g ngx-build-plus:wc-polyfill --project dashboard-tile \n<\/div><\/pre>\n<p>Please note that you need to reference the <code>CUSTOM_ELEMENTS_SCHEMA<\/code> in your respective modules if you want to use a custom element within an Angular Component:<\/p>\n<pre class=\"language-typescript\"><div><span class=\"hljs-meta\">@NgModule<\/span>({\n  declarations: [\n    AppComponent\n  ],\n  imports: [\n    BrowserModule\n  ],\n  providers: [],\n  schemas: [CUSTOM_ELEMENTS_SCHEMA],\n  bootstrap: [AppComponent]\n})\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">class<\/span> AppModule { }\n<\/div><\/pre>\n<p>After starting the solution (<code>npm start<\/code>) you should see something like this in Chrome:<\/p>\n<p><img decoding=\"async\" class=\"img\" src=\"http:\/\/www1.angulararchitects.io.dedi1415.your-server.de\/wp-content\/uploads\/2017\/09\/build-02.png\" alt=\"\"><\/p>\n<blockquote class=\"info\"><p>\nAngular Elements comes with an alternative polyfill that is registered within your <code>angular.json<\/code> when installing it with <code>ng add @angular\/elements<\/code>. This one is far more lightweight than the one I'm using here. However, it just can be used with browsers supporting EcmaScript 2015 and above. Hence, when you don't need to target Internet Explorer, this one should be prefered.\n<\/p><\/blockquote>\n<h2 id=\"differential-loading\">Differential Loading<\/h2>\n<p>To leverage differential loading, just point to EcmaScript 2015+ in your <code>tsconfig.json<\/code> and make sure the <code>browserslist<\/code> file in your workspace root points to at least one EcmaScript 5 browser (which is normally the case). This makes the CLI build two versions of your bundles -- one with EcmaScript 5 and another one with EcmaScript 2015.<\/p>\n<p>As now, newer browsers get EcmaScript 2015 code, we don't need to include the above shown <code>custom-elements-es5-adapter.js<\/code> script.<\/p>\n<h2 id=\"build\">Build<\/h2>\n<p>Now, let's create a bundle for our web component using <code>ng build<\/code>:<\/p>\n<pre><div>ng build --prod\n<\/div><\/pre>\n<p>This gives us several (!) bundles:<\/p>\n<p><img decoding=\"async\" class=\"img\" src=\"http:\/\/www1.angulararchitects.io.dedi1415.your-server.de\/wp-content\/uploads\/2019\/11\/build-09.png\" alt=\"\"><\/p>\n<p>While this is ok for an ordinary SPA, it's far too much for a simple web component. In our case, having just one self-contained bundle would be better.<\/p>\n<p>My above mentioned community project <code>ngx-build-plus<\/code> provides  a simple solution for this with its <code>--single-bundle<\/code> switch:<\/p>\n<pre><div>ng build --prod --single-bundle\n<\/div><\/pre>\n<p>After running this, we get one bundle called <code>main<\/code> instad of  <code>main<\/code>, <code>vendor<\/code> and <code>runtime<\/code>:<\/p>\n<p><img decoding=\"async\" class=\"img\" src=\"http:\/\/www1.angulararchitects.io.dedi1415.your-server.de\/wp-content\/uploads\/2019\/11\/build-08.png\" alt=\"\"><\/p>\n<p>The latest version of <code>ngx-build-plus<\/code> still emits <code>polyfills<\/code>, <code>styles<\/code> and <code>scripts<\/code> in addition. This comes in handy for testing. However, you will normally not ship these files because the consuming application will very likely have its own verions of them.<\/p>\n<blockquote class=\"info\"><p>\nAn alternative to <code>--single-bundle<\/code> you see sometimes is manually copying the four bundles into one file. Unfortunately, this does not work if you have more than one such meta-bundle. The reason is that webpack is exposing a global variable and this would get overwritten when using several such bundles that have been compiled separately.\n<\/p><\/blockquote>\n<p>When you look at the bundle sizes, you immediately realize that they are far to huge for such a simple web component. That's because they include Angular, RxJS and other libs -- at least the parts of it that have not been tree-shaken off. It's even worse: If you compile several bundles separately, each of them get a copy of those libraries:<\/p>\n<p><img decoding=\"async\" class=\"img\" src=\"http:\/\/www1.angulararchitects.io.dedi1415.your-server.de\/wp-content\/uploads\/2017\/09\/build-duplication.png\" alt=\"\"><\/p>\n<p>This is where Ivy comes in.<\/p>\n<h2 id=\"ivy\">Ivy<\/h2>\n<p>Beginning with Angular 9 we will get the new Ivy compiler by default. It makes Angular more tree-shakable and compiles the UI part of components down to code which is quite close to the DOM. For this reason, typical web components will benefit a lot from Ivy and the resulting bundle won't need much of Angular.<\/p>\n<p><strong>In the best case,<\/strong> two separately generated bundles with Angular Elements will look like this:<\/p>\n<p><img decoding=\"async\" class=\"img\" src=\"http:\/\/www1.angulararchitects.io.dedi1415.your-server.de\/wp-content\/uploads\/2017\/09\/build-04a.png\" alt=\"\"><\/p>\n<p>They just contain their component code and a very tiny remainder of Angular which acts as the runtime. As mentioned: in the best case!<\/p>\n<p>However, while Ivy has a lot of potential, we should not expect wonders like <a href=\"https:\/\/twitter.com\/mgechev\">Minko Gechev<\/a> who is now part of the Angular Team <a href=\"https:\/\/twitter.com\/mgechev\/status\/1073005030054064128\">told us at twitter<\/a>:<\/p>\n<blockquote class=\"info\"><p>\nIvy will enable new features in Angular, which will come gradually, and it <em>may<\/em> reduce your app size but do not expect wonders - it will not make your JS disappear. I'd <em>strongly<\/em> recommend to not wait for ivy but instead, shrink JavaScript bundles today <a href=\"https:\/\/angular.io\/guide\/lazy-loading-ngmodules\">https:\/\/angular.io\/guide\/lazy-loading-ngmodules<\/a> \u2026\n<\/p><\/blockquote>\n<p>Especially, if our components contain lots of libraries besides UI code, Ivy will not help much. Or to put it in another way: It cannot make the used parts of packages like <code>@angular\/forms<\/code> or <code>@angular\/common\/http<\/code> disappear.<\/p>\n<p>In this case, we very likely need to find a way to share such dependencies among separately built bundles. This leads to an idea presented in one of the following sections.<\/p>\n<h2 id=\"sharing-libraries\">Sharing Libraries<\/h2>\n<p>In order to share libraries like <code>@angular\/common\/http<\/code> which is used in our above shown Angular Element, we could load them into the web site's global scope and reuse them in our web component bundles:<\/p>\n<p><img decoding=\"async\" class=\"img\" src=\"http:\/\/www1.angulararchitects.io.dedi1415.your-server.de\/wp-content\/uploads\/2017\/09\/build-05.png\" alt=\"\"><\/p>\n<p>This is something that was quite usual some years ago. Think about using jQuery. We needed to load jQuery and jQuery UI once and the bundles with our jQuery widgets just referenced them.<\/p>\n<p>However, Angular projects are normally built into several bundles that only know each other and other bundles cannot easily access their code.<\/p>\n<p>To solve this issue, Angular's <a href=\"https:\/\/twitter.com\/robwormald\">Rob Wormald<\/a> came up with a interesting idea: Let's tweak the build process so that the generated bundles expect the shared libraries not to be part of them but are located within the global scope. In order to make this possible, we need to find a way to put Angular and its dependencies there.<\/p>\n<p>Fortunately, the Angular package format prescribes to expose Angular libraries also as UMD bundles and they do this job. In the case of Angular itself, they register themselves at <code>window.ng.core<\/code>, <code>window.ng.common<\/code>, etc.<\/p>\n<p>This involves a lot of manual steps I've automated with another schematic:<\/p>\n<pre><div>ng g ngx-build-plus:externals --project dashboard-tile\n<\/div><\/pre>\n<p>To compile everything, use this npm script generated by <code>ngx-build-plus<\/code>:<\/p>\n<pre><div>npm run build:dashboard-tile:externals\n<\/div><\/pre>\n<p>After this, you can switch to your <code>dist<\/code> folder and try out your solution:<\/p>\n<pre><div>npm i -g live-server\ncd dist\ncd dashboard-tile\nlive-server\n<\/div><\/pre>\n<h2 id=\"behind-the-covers\">Behind the covers<\/h2>\n<p>Now, let's talk about what happened here. The schematic we've executed created a partial webpack configuration, which defines where the shared libraries can be found within the browser's <code>window<\/code> object.<\/p>\n<pre class=\"language-javascript\"><div><span class=\"hljs-keyword\">const<\/span> webpack = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'webpack'<\/span>);\n\n<span class=\"hljs-built_in\">module<\/span>.exports = {\n    <span class=\"hljs-string\">\"externals\"<\/span>: {\n        <span class=\"hljs-string\">\"rxjs\"<\/span>: <span class=\"hljs-string\">\"rxjs\"<\/span>,\n        <span class=\"hljs-string\">\"@angular\/core\"<\/span>: <span class=\"hljs-string\">\"ng.core\"<\/span>,\n        <span class=\"hljs-string\">\"@angular\/common\"<\/span>: <span class=\"hljs-string\">\"ng.common\"<\/span>,\n        <span class=\"hljs-string\">\"@angular\/common\/http\"<\/span>: <span class=\"hljs-string\">\"ng.common.http\"<\/span>,\n        <span class=\"hljs-string\">\"@angular\/platform-browser\"<\/span>: <span class=\"hljs-string\">\"ng.platformBrowser\"<\/span>,\n        <span class=\"hljs-string\">\"@angular\/platform-browser-dynamic\"<\/span>: <span class=\"hljs-string\">\"ng.platformBrowserDynamic\"<\/span>,\n        <span class=\"hljs-string\">\"@angular\/compiler\"<\/span>: <span class=\"hljs-string\">\"ng.compiler\"<\/span>,\n        <span class=\"hljs-string\">\"@angular\/elements\"<\/span>: <span class=\"hljs-string\">\"ng.elements\"<\/span>,\n\n        <span class=\"hljs-comment\">\/\/ Uncomment and add to scripts in angular.json if needed<\/span>\n        <span class=\"hljs-comment\">\/\/ \"@angular\/router\": \"ng.router\",<\/span>\n        <span class=\"hljs-comment\">\/\/ \"@angular\/forms\": \"ng.forms\"<\/span>\n    }\n}\n<\/div><\/pre>\n<p>When compiling, the CLI <strong>does not<\/strong> include these dependencies in your bundles. Instead it just uses references, e. g. to <code>window.ng.core<\/code> or <code>window.ng.common<\/code>.<\/p>\n<p>To load Angular and RxJS into the window object, the schematic also references the respective UMD bundles in the <code>scripts<\/code> section within <code>angular.json<\/code>:<\/p>\n<pre class=\"language-json\"><div><span class=\"hljs-string\">\"scripts\"<\/span>: [\n  [...]\n  <span class=\"hljs-string\">\"node_modules\/rxjs\/bundles\/rxjs.umd.js\"<\/span>,\n  <span class=\"hljs-string\">\"node_modules\/@angular\/core\/bundles\/core.umd.js\"<\/span>,\n  <span class=\"hljs-string\">\"node_modules\/@angular\/common\/bundles\/common.umd.js\"<\/span>,\n  <span class=\"hljs-string\">\"node_modules\/@angular\/common\/bundles\/common-http.umd.js\"<\/span>,\n  <span class=\"hljs-string\">\"node_modules\/@angular\/compiler\/bundles\/compiler.umd.js\"<\/span>,\n  <span class=\"hljs-string\">\"node_modules\/@angular\/elements\/bundles\/elements.umd.js\"<\/span>,\n  <span class=\"hljs-string\">\"node_modules\/@angular\/platform-browser\/bundles\/platform-browser.umd.js\"<\/span>,\n  <span class=\"hljs-string\">\"node_modules\/@angular\/platform-browser-dynamic\/bundles\/platform-browser-dynamic.umd.js\"<\/span>\n]\n<\/div><\/pre>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>There are several strategies for building web components and they differ from those normally used for building full blown SPAs. Ivy will help a lot with reducing the bundle sizes if your project mainly contains UI code. Besides this, it also improves tree-shakability in general.<\/p>\n<p>For sharing libraries you can use externals. The community project <code>ngx-build-plus<\/code> helps with this and with creating a single bundle. It also helps with installing polyfills for legacy browsers.<\/p>\n<p>In addition, differential loading makes sure that only browsers which needs the polyfills get them. It also makes sure that modern browsers get smaller and more optimized EcmaScript 2015+ bundles.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>with the CLI<\/p>\n","protected":false},"author":9,"featured_media":3006,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_price":"","_stock":"","_tribe_ticket_header":"","_tribe_default_ticket_provider":"","_ticket_start_date":"","_ticket_end_date":"","_tribe_ticket_show_description":"","_tribe_ticket_show_not_going":false,"_tribe_ticket_use_global_stock":"","_tribe_ticket_global_stock_level":"","_global_stock_mode":"","_global_stock_cap":"","_tribe_rsvp_for_event":"","_tribe_ticket_going_count":"","_tribe_ticket_not_going_count":"","_tribe_tickets_list":"[]","_tribe_ticket_has_attendee_info_fields":false,"footnotes":""},"categories":[18],"tags":[],"class_list":["post-212","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Your options for building Angular Elements - ANGULARarchitects<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Your options for building Angular Elements - ANGULARarchitects\" \/>\n<meta property=\"og:description\" content=\"with the CLI\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/\" \/>\n<meta property=\"og:site_name\" content=\"ANGULARarchitects\" \/>\n<meta property=\"article:published_time\" content=\"2019-05-01T03:00:41+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2017\/09\/building-angular-elements-with-the-cli.png\" \/>\n\t<meta property=\"og:image:width\" content=\"640\" \/>\n\t<meta property=\"og:image:height\" content=\"426\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Manfred Steyer, GDE\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@daniel\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Manfred Steyer, GDE\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/your-options-for-building-angular-elements\/\"},\"author\":{\"name\":\"Manfred Steyer, GDE\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951\"},\"headline\":\"Your options for building Angular Elements\",\"datePublished\":\"2019-05-01T03:00:41+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/your-options-for-building-angular-elements\/\"},\"wordCount\":1629,\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2017\/09\/building-angular-elements-with-the-cli.png\",\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/your-options-for-building-angular-elements\/\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/\",\"name\":\"Your options for building Angular Elements - ANGULARarchitects\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2017\/09\/building-angular-elements-with-the-cli.png\",\"datePublished\":\"2019-05-01T03:00:41+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/#primaryimage\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2017\/09\/building-angular-elements-with-the-cli.png\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2017\/09\/building-angular-elements-with-the-cli.png\",\"width\":640,\"height\":426},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.angulararchitects.io\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Your options for building Angular Elements\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"name\":\"ANGULARarchitects\",\"description\":\"AngularArchitects.io\",\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\",\"name\":\"ANGULARarchitects\",\"alternateName\":\"SOFTWAREarchitects\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg\",\"width\":644,\"height\":216,\"caption\":\"ANGULARarchitects\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/github.com\/angular-architects\",\"https:\/\/www.linkedin.com\/company\/angular-architects\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951\",\"name\":\"Manfred Steyer, GDE\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g\",\"caption\":\"Manfred Steyer, GDE\"},\"sameAs\":[\"https:\/\/x.com\/daniel\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Your options for building Angular Elements - ANGULARarchitects","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/","og_locale":"en_US","og_type":"article","og_title":"Your options for building Angular Elements - ANGULARarchitects","og_description":"with the CLI","og_url":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/","og_site_name":"ANGULARarchitects","article_published_time":"2019-05-01T03:00:41+00:00","og_image":[{"width":640,"height":426,"url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2017\/09\/building-angular-elements-with-the-cli.png","type":"image\/png"}],"author":"Manfred Steyer, GDE","twitter_card":"summary_large_image","twitter_creator":"@daniel","twitter_misc":{"Written by":"Manfred Steyer, GDE","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/#article","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/your-options-for-building-angular-elements\/"},"author":{"name":"Manfred Steyer, GDE","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951"},"headline":"Your options for building Angular Elements","datePublished":"2019-05-01T03:00:41+00:00","mainEntityOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/your-options-for-building-angular-elements\/"},"wordCount":1629,"publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2017\/09\/building-angular-elements-with-the-cli.png","inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/your-options-for-building-angular-elements\/","url":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/","name":"Your options for building Angular Elements - ANGULARarchitects","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/#primaryimage"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2017\/09\/building-angular-elements-with-the-cli.png","datePublished":"2019-05-01T03:00:41+00:00","breadcrumb":{"@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/#primaryimage","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2017\/09\/building-angular-elements-with-the-cli.png","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2017\/09\/building-angular-elements-with-the-cli.png","width":640,"height":426},{"@type":"BreadcrumbList","@id":"https:\/\/www.angulararchitects.io\/en\/aktuelles\/your-options-for-building-angular-elements\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.angulararchitects.io\/en\/"},{"@type":"ListItem","position":2,"name":"Your options for building Angular Elements"}]},{"@type":"WebSite","@id":"https:\/\/www.angulararchitects.io\/en\/#website","url":"https:\/\/www.angulararchitects.io\/en\/","name":"ANGULARarchitects","description":"AngularArchitects.io","publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.angulararchitects.io\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.angulararchitects.io\/en\/#organization","name":"ANGULARarchitects","alternateName":"SOFTWAREarchitects","url":"https:\/\/www.angulararchitects.io\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2023\/07\/AA-Logo-RGB-horizontal-inside-knowledge-black.svg","width":644,"height":216,"caption":"ANGULARarchitects"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/github.com\/angular-architects","https:\/\/www.linkedin.com\/company\/angular-architects\/"]},{"@type":"Person","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/15628efa7af4475ffaaeeb26c5112951","name":"Manfred Steyer, GDE","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a0b59539674d8b71ea1c1f4764b11244b5f499203f1d11b40f37d8f3f90be033?s=96&d=mm&r=g","caption":"Manfred Steyer, GDE"},"sameAs":["https:\/\/x.com\/daniel"]}]}},"_links":{"self":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/212","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/users\/9"}],"replies":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/comments?post=212"}],"version-history":[{"count":0,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/212\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media\/3006"}],"wp:attachment":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media?parent=212"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/categories?post=212"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/tags?post=212"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}