What’s new in Angular 8!
Tags: ionic, angular
Published: 2020-03-26 17:08:24

<main role="main"><article class=" u-minHeight100vhOffset65 u-overflowHidden postArticle postArticle--full is-supplementalPostContentLoaded is-withAccentColors" lang="en"><div class="postArticle-content js-postField js-notesSource editable" id="editor_6" g_editable="true" role="textbox" contenteditable="true" data-default-value="Title
Tell your story…" spellcheck="false"><section name="fad0" class="section section--body section--first section--last"><div class="section-divider"><hr class="section-divider"></div><div class="section-content"><div class="section-inner sectionLayout--insetColumn"><p name="bb25" class="graf graf--p graf-after--figure"><strong class="markup--strong markup--p-strong">Angular 8 was just released!</strong></p><p name="225c" class="graf graf--p graf-after--p">As planned, there were no surprises: the update of the framework and CLI can be done by using <em class="markup--em markup--p-em">ng update</em> and the new features are a welcome addition in line with the motto “evolution instead of revolution”.</p><p name="7253" class="graf graf--p graf-after--p">In this article, I will cover the most important new features of Angular 8 and the corresponding Angular CLI 8.</p><h3 name="7bac" class="graf graf--h3 graf-after--p">TypeScript 3.4</h3><p name="5fc7" class="graf graf--p graf-after--h3 is-selected">Angular 8.0 now supports TypeScript 3.4, and even requires it, so you’ll need to upgrade.</p><p name="2f84" class="graf graf--p graf-after--p">You can checkout out what <a href="https://devblogs.microsoft.com/typescript/announcing-typescript-3-3/"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">TypeScript 3.3</a> and <a href="https://devblogs.microsoft.com/typescript/announcing-typescript-3-4/"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">TypeScript 3.4</a> brings on the Microsoft blog.</p><h3 name="ef43" class="graf graf--h3 graf-after--p">Breaking change in ViewChild and ContentChild</h3><p name="7560" class="graf graf--p graf-after--h3">There is a breaking change in the usage of <em class="markup--em markup--p-em">ViewChild</em> and <em class="markup--em markup--p-em">ContentChild,</em> which unfortunately didn’t always show a consistent behavior in the past. While they were used in earlier versions for a component to request an element not inside a structural directive like <em class="markup--em markup--p-em">ngIf</em> or <em class="markup--em markup--p-em">ngFor</em>, the query result was already available in <em class="markup--em markup--p-em">ngOnInit. </em>Otherwise, the program code could access it at the earliest in <em class="markup--em markup--p-em">ngAfterViewInit</em> (or<em class="markup--em markup--p-em"> ngAfterContentInit </em>for<em class="markup--em markup--p-em">ContentChild</em>). For elements that were only loaded into the DOM at a later time due to data binding, the program code had to insert <em class="markup--em markup--p-em">ngAfterViewChecked</em> or, respectively, <em class="markup--em markup--p-em">ngAfterContentChecked</em>.</p><p name="161d" class="graf graf--p graf-after--p">As this behavior was confusing, the component must now specify when the resolution should take place:</p><p name="cdce" class="graf graf--p graf-after--p"><code class="markup--code markup--p-code u-paddingRight0 u-marginRight0">@ViewChild('info', { <strong class="markup--strong markup--p-strong">static</strong>: <strong class="markup--strong markup--p-strong">false</strong></code> <code class="markup--code markup--p-code">})</code></p><p name="022d" class="graf graf--p graf-after--p"><code class="markup--code markup--p-code">paragraph: ElementRef;</code></p><p name="d6a1" class="graf graf--p graf-after--p">If <em class="markup--em markup--p-em">static</em> has the value <em class="markup--em markup--p-em">true</em>, Angular tries to find the element when initializing the component. This only works if it is not in a structural directive. When using <em class="markup--em markup--p-em">static: false, </em>the resolution takes places after initiating or refreshing the view.</p><p name="5e8e" class="graf graf--p graf-after--p">The command <em class="markup--em markup--p-em">ng update</em> automatically tries to enter the correct value here. If that is not possible, it adds a comment with a TODO in its place.</p><p name="8b17" class="graf graf--p graf-after--p">Queries with the related decorators <em class="markup--em markup--p-em">ViewChildren</em> and <em class="markup--em markup--p-em">ContentChildren</em> are not affected by this change. They have always exhibited a dynamic behavior in the sense of <em class="markup--em markup--p-em">static: false</em>.</p><h3 name="c207" class="graf graf--h3 graf-after--p">Differential loading</h3><p name="fc52" class="graf graf--p graf-after--h3">Your Angular 8 apps will now be automagically more performant, thanks to differential loading.</p><p name="07e1" class="graf graf--p graf-after--p">Until now, it was common to compile applications to good old ECMAScript 5, since this “JavaScript of our fathers” runs almost anywhere today. This means that both IE 11 and the web crawler behind the Google search engine can execute the program code.</p><p name="32b2" class="graf graf--p graf-after--p">However, the new ECMAScript 2015 and its subsequent versions are more efficient: these versions allow more compact bundles and the browser can also interpret them more efficiently. Since it was previously common to retreat to ECMAScript 5 as the smallest common denominator, other modern browsers, unfortunately, couldn’t use these advantages.</p><p name="2f9c" class="graf graf--p graf-after--p">This ends now: starting with version 8, the CLI includes a feature that is named differential loading. The idea behind it is to provide two groups of bundles: one is based on ECMAScript 5 and addresses older browsers, the other is based on a younger ECMAScript version, e.g. ECMAScript 2015, and offers modern browsers the mentioned advantages.</p><p name="dfae" class="graf graf--p graf-after--p">There isn’t much you need to do in order to activate differential loading: all that is necessary is to set an upper and a lower bar for the ECMAScript versions to be supported. The upper bar is entered in the <em class="markup--em markup--p-em">tsconfig.json</em> as follows:</p><p name="bd60" class="graf graf--p graf-after--p"><code class="markup--code markup--p-code">"target": "es2015"</code></p><p name="528c" class="graf graf--p graf-after--p">The lower bar, on the other hand, is defined by a browserslist. It is a file that identifies many browsers to be supported, according to certain criteria like market shares. They can be stored e.g. in the file <em class="markup--em markup--p-em">browserslist</em>, which the CLI meanwhile creates in <em class="markup--em markup--p-em">projectroot</em> when generating a new project:</p><p name="faaa" class="graf graf--p graf-after--p"><code class="markup--code markup--p-code">&gt; 0.5%</code></p><p name="089b" class="graf graf--p graf-after--p"><code class="markup--code markup--p-code">last 2</code> <code class="markup--code markup--p-code">versions</code></p><p name="8910" class="graf graf--p graf-after--p"><code class="markup--code markup--p-code">Firefox ESR</code></p><p name="1b12" class="graf graf--p graf-after--p"><code class="markup--code markup--p-code">not dead</code></p><p name="0161" class="graf graf--p graf-after--p"><code class="markup--code markup--p-code">IE 9-11</code></p><p name="e42c" class="graf graf--p graf-after--p">In the illustrated case, the <em class="markup--em markup--p-em">browserslist</em> points to ECMAScript 5 browsers with the entry IE 9–11. Thereby, the CLI determines the lower bar as this version. If the CLI receives the instruction to create a build (<em class="markup--em markup--p-em">ng build</em>), compiling and bundling processes will take place for both versions:</p><figure tabindex="0" contenteditable="false" name="ef57" class="graf graf--figure graf-after--p is-defaultValue"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 345px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 49.3%;"></div><img class="graf-image" data-image-id="0*Uq4k3kRkWey0rg_F.png" data-width="1024" data-height="505" src="https://cdn-images-1.medium.com/max/600/0*Uq4k3kRkWey0rg_F.png"><div class="crosshair u-ignoreBlock"></div></div></figure><p name="c41c" class="graf graf--p graf-after--figure">Build for differential loading</p><p name="c22a" class="graf graf--p graf-after--p">The disadvantage of this process becomes obvious here: the time required for the build process is doubled.</p><p name="d89a" class="graf graf--p graf-after--p">The different browsers can now decide which version of the bundles to load. For this, they receive the <em class="markup--em markup--p-em">script</em>references in the <em class="markup--em markup--p-em">index.html </em>additions: those pointing to ECMAScript 5 bundles receive the addition <em class="markup--em markup--p-em">nomodule. </em>This prevents browsers with support for ECMAScript modules, and thereby ECMAScript 2015 and newer, from ignoring the reference. The ECMAScript 2015+ bundles, on the other hand, are implemented by the CLI via <em class="markup--em markup--p-em">type=”module”.</em> Thus, older browsers will ignore these script tags:</p><p name="f707" class="graf graf--p graf-after--p"><code class="markup--code markup--p-code">&lt;script src="main-es2015.js"</code> <code class="markup--code markup--p-code">type="module"&gt;&lt;/script&gt;</code></p><p name="10c9" class="graf graf--p graf-after--p"><code class="markup--code markup--p-code">&lt;script src="main-es5.js"</code> <code class="markup--code markup--p-code">nomodule&gt;&lt;/script&gt;</code></p><p name="6e33" class="graf graf--p graf-after--p">In contrast to <em class="markup--em markup--p-em">ng build</em>, all other CLI commands use only (!) the upper bar. In the illustrated case, that is ECMAScript 2015. This happens, among others, for efficiency reasons: especially during debugging and testing, developers want to see a result as soon as possible without being required to wait for a second build.</p><p name="eb11" class="graf graf--p graf-after--p">You don’t have to do anything special to benefit from differential loading, the <code class="markup--code markup--p-code">ng build</code> command with the <code class="markup--code markup--p-code">--prod</code> flag will take care of bundling everything so that differential loading is working out of the box:</p><pre name="2b01" class="graf graf--pre graf-after--p"><code class="markup--code markup--pre-code">$ ng build --prod</code></pre><h3 name="5484" class="graf graf--h3 graf-after--pre">Ivy</h3><p name="4f8a" class="graf graf--p graf-after--h3">Ivy is obviously a huge part of this release, and it took most of the effort from the team these last month. There is so much to say about Ivy that I wrote a <a href="https://blog.ninja-squad.com/2019/05/07/what-is-angular-ivy/"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">dedicated article about it</a>.</p><p name="0fa3" class="graf graf--p graf-after--p">TL;DR: Ivy is the new compiler/runtime of Angular. It will enable very cool features in the future, but it is currently focused on not breaking existing applications.</p><p name="a483" class="graf graf--p graf-after--p">Angular 8.0 is the first release to officially offer a switch to opt-in into Ivy. There are no real gains to do so right now, but you can give it a try to see if nothing breaks in your application. Because, at some point, probably in v9, Ivy will be the default. So the Angular team hopes the community will anticipate the switch and provide feedback, and that we’ll catch all the remaining issues before v9.</p><p name="09d6" class="graf graf--p graf-after--p">We tried it on several of our apps and already caught a few regressions, so we would strongly advise to not use it blindly in production 😄.</p><p name="84cc" class="graf graf--p graf-after--p">If you feel adventurous, you can add <code class="markup--code markup--p-code">"enableIvy": true</code> in your <code class="markup--code markup--p-code">angularCompilerOptions</code>, and restart your application: it now uses Ivy! Check <a href="https://blog.ninja-squad.com/2019/05/07/what-is-angular-ivy/"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">our article</a> and the <a href="https://angular.io/guide/ivy"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">official guide for more info</a>.</p><figure tabindex="0" contenteditable="false" name="097a" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 390px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 55.7%;"></div><img class="graf-image" data-image-id="0*PvBPsMwNc0zyU0LP.png" data-width="1024" data-height="570" src="https://cdn-images-1.medium.com/max/600/0*PvBPsMwNc0zyU0LP.png"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Bundle Size</figcaption></figure><h3 name="5c75" class="graf graf--h3 graf-after--figure">Bazel Support</h3><p name="0c31" class="graf graf--p graf-after--h3">One of the new features of Angular 8 is the possibility to (more easily) build your CLI application with Bazel.</p><p name="156b" class="graf graf--p graf-after--p"><a href="https://bazel.build/"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">Bazel</a> is a build tool developed and massively used by Google, as it can build pretty much any language. The Angular framework itself is built with Bazel.</p><p name="10ee" class="graf graf--p graf-after--p">The key advantages of Bazel are:</p><ul class="postList"><li name="6432" class="graf graf--li graf-after--p">the possibility of building your backends and frontends with the same tool</li><li name="850f" class="graf graf--li graf-after--li">the incremental build and tests</li><li name="db0e" class="graf graf--li graf-after--li">the possibility to have remote builds (and cache) on a build farm</li></ul><h3 name="24d4" class="graf graf--h3 graf-after--li">Service worker</h3><h4 name="a6fe" class="graf graf--h4 graf-after--h3">Registration strategy</h4><p name="e6d8" class="graf graf--p graf-after--h4">The service worker registration has a new option that allows to specify when the registration should take place. Previously, the service worker was waiting for the application to be stable to register, to avoid slowing the start of the application. But if you were starting a recurring asynchronous task (like a polling process) on application bootstrap, the application was never stable as Angular considers an application to be stable if there is no pending task. So the service worker never registered, and you had to manually workaround it. With the new <code class="markup--code markup--p-code">registrationStrategy</code> option, you can now let Angular handle this. There are several values possible:</p><ul class="postList"><li name="4d00" class="graf graf--li graf-after--p"><code class="markup--code markup--li-code">registerWhenStable</code>, the default, as explained above</li><li name="3ca5" class="graf graf--li graf-after--li"><code class="markup--code markup--li-code">registerImmediately</code>, which doesn’t wait for the app to be stable and registers the Service Worker right away</li><li name="3fb1" class="graf graf--li graf-after--li"><code class="markup--code markup--li-code">registerDelay:$TIMEOUT</code> with <code class="markup--code markup--li-code">$TIMEOUT</code> being the number of milliseconds to wait before the registration</li><li name="1cf9" class="graf graf--li graf-after--li">a function returning an Observable, to define a custom strategy. The Service Worker will then register when the Observable emits its first value.</li></ul><p name="f1c8" class="graf graf--p graf-after--li">For example, if you want to register the Service Worker after 2 seconds:</p><pre name="4fc8" class="graf graf--pre graf-after--p"><code class="markup--code markup--pre-code">providers: [<br>  ServiceWorkerModule.register('/ngsw-worker.js', {<br>    enabled: environment.production,<br>    registrationStrategy: 'registerDelay:2000'<br>  }),<br>  // ...<br>]</code></pre><h4 name="252d" class="graf graf--h4 graf-after--pre">Bypass a Service&nbsp;Worker</h4><p name="52cc" class="graf graf--p graf-after--h4">It is now also possible to bypass the Service Worker for a specific request by adding the <code class="markup--code markup--p-code">ngsw-bypass</code> header.</p><pre name="6b48" class="graf graf--pre graf-after--p"><code class="markup--code markup--pre-code">this.http.get('api/users', { headers: { 'ngsw-bypass': true } });</code></pre><h4 name="5382" class="graf graf--h4 graf-after--pre">Multiple apps on sub-domains</h4><p name="cf6c" class="graf graf--p graf-after--h4">Previously, it was not possible to have multiple applications using<code class="markup--code markup--p-code">@angular/service-worker</code> on different sub-paths of the same domain, because each Service Worker would overwrite the caches of the others… This is now fixed!</p><h3 name="5f6c" class="graf graf--h3 graf-after--p">Forms</h3><h4 name="2a2f" class="graf graf--h4 graf-after--h3">markAllAsTouched</h4><p name="6b39" class="graf graf--p graf-after--h4">The <code class="markup--code markup--p-code">AbstractControl</code> class now offers a new method <code class="markup--code markup--p-code">markAllAsTouched</code>in addition to the existing <code class="markup--code markup--p-code">markAsDirty</code>, <code class="markup--code markup--p-code">markAsTouched</code>, <code class="markup--code markup--p-code">markAsPending</code>, etc. <code class="markup--code markup--p-code">AbstractControl</code> is the parent class of <code class="markup--code markup--p-code">FormGroup</code>, <code class="markup--code markup--p-code">FormControl</code>, <code class="markup--code markup--p-code">FormArray</code>, so the method is available on all reactive form entities.</p><p name="35d7" class="graf graf--p graf-after--p">Like <code class="markup--code markup--p-code">markAsTouched</code>, this new method marks a control as <code class="markup--code markup--p-code">touched</code> but also all its descendants.</p><pre name="b74e" class="graf graf--pre graf-after--p"><code class="markup--code markup--pre-code">form.markAllAsTouched();</code></pre><h4 name="fb47" class="graf graf--h4 graf-after--pre">FormArray.clear</h4><p name="fd10" class="graf graf--p graf-after--h4">The <code class="markup--code markup--p-code">FormArray</code> class now also offers a <code class="markup--code markup--p-code">clear</code> method, to quickly remove all the controls it contains. You previously had to loop over the controls to remove them one by one.</p><pre name="7fb1" class="graf graf--pre graf-after--p"><code class="markup--code markup--pre-code">// `users` is initialized with 2 users<br>const users = fb.array([user1, user2]);<br>users.clear();<br>// users is now empty</code></pre><h3 name="fa3f" class="graf graf--h3 graf-after--pre">Dynamic imports for lazy&nbsp;routes</h3><p name="5473" class="graf graf--p graf-after--h3"><a href="https://alligator.io/angular/lazy-loading/"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">Lazy-loaded routes</a> now use the standard <a href="https://developers.google.com/web/updates/2017/11/dynamic-import"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">dynamic import</a> syntax instead of a custom string. This means that TypeScript and linters will be better able to complain when modules are missing or misspelled.</p><p name="03dd" class="graf graf--p graf-after--p">So a lazy-loaded import that looked like this:</p><pre name="3284" class="graf graf--pre graf-after--p"><code class="markup--code markup--pre-code">{ path: '/cart', loadChildren: './cart/cart.module#CartModule' }</code></pre><p name="eb3b" class="graf graf--p graf-after--pre">Will now look like this:</p><pre name="8e1d" class="graf graf--pre graf-after--p"><code class="markup--code markup--pre-code">{ path: `/cart`, loadChildren: () =&gt; import(`./cart/cart.module`).then(m =&gt; m.CartModule) }</code></pre><p name="e82b" class="graf graf--p graf-after--pre">The change in syntax will be taken care of for you if you’re using the <code class="markup--code markup--p-code">ng upgrade</code>command to upgrade your app.</p><h3 name="726b" class="graf graf--h3 graf-after--p">New features for ngUpgrade</h3><p name="4df1" class="graf graf--p graf-after--h3">Up until now, one problem in the hybrid operation of AngularJS 1.x and Angular with ngUpgrade has been that the routers of both frameworks have at times been dueling over the URL. This led to side effects that were difficult to comprehend. In order to avoid this, the possibility of using the identical <em class="markup--em markup--p-em">Location</em> service for accessing the URL in both framework versions has been added.</p><p name="c501" class="graf graf--p graf-after--p">To achieve this, the Angular team has extended the possibilities of Angular’s <em class="markup--em markup--p-em">Location</em> services and thereby provided a substitute for <em class="markup--em markup--p-em">$location</em> in AngularJS.</p><p name="f938" class="graf graf--p graf-after--p">For this reason, the new method <em class="markup--em markup--p-em">onUrlChange </em>for monitoring URL changes, among other modifications, has been added in the <em class="markup--em markup--p-em">Location</em> service:</p><pre name="d258" class="graf graf--pre graf-after--p"><code class="markup--code markup--pre-code u-paddingRight0 u-marginRight0">export <strong class="markup--strong markup--pre-strong">class</strong></code> <code class="markup--code markup--pre-code">AppComponent {<br>constructor(loc: Location, pLoc: PlatformLocation) {<br>loc.onUrlChange((url) =&gt; console.debug('url change', url));<br>console.debug('hostname: ', pLoc.hostname);<br>}<br>}</code></pre><p name="d1eb" class="graf graf--p graf-after--pre">The <em class="markup--em markup--p-em">PlatformLocation</em> service offers additional access to the individual parts of the URL. A detailed description on how the <em class="markup--em markup--p-em">$location</em> substitute, which is based on it, is used for a better interlacing of both frameworks, can be found <a href="https://next.angular.io/guide/upgrade#using-the-unified-angular-location-service"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">here</a>. Additionally, there you can now find an idea for lazy loading of AngularJS, which is based on the aforementioned dynamic ECMAScript imports.</p><h3 name="7d96" class="graf graf--h3 graf-after--p">CLI workflow improvements</h3><p name="93d5" class="graf graf--p graf-after--h3">The CLI is continuing to improve, and now the <code class="markup--code markup--p-code">ng build</code>, <code class="markup--code markup--p-code">ng test</code> and <code class="markup--code markup--p-code">ng run</code>are equipped to be extended by 3rd-party libraries and tool. For example, AngularFire already makes use of these new capabilities with a <code class="markup--code markup--p-code">deploy</code> command</p><h3 name="3328" class="graf graf--h3 graf-after--p">Deprecated APIs and&nbsp;Features</h3><p name="d7ab" class="graf graf--p graf-after--h3">Angular aims to balance innovation and stability in their framework and to do that they have removed or replaced some features &amp; API’S so that Angular can stay updated with latest practices, changing dependencies, or changes in the platform itself.</p><p name="a9aa" class="graf graf--p graf-after--p">To make these transitions easy they deprecate APIs and features for a period of time before removing them which provide developers time to update your apps to the latest APIs and best practices.</p><ul class="postList"><li name="a83c" class="graf graf--li graf-after--p">Web Tracing Framework integration</li><li name="09b3" class="graf graf--li graf-after--li"><code class="markup--code markup--li-code">@angular/platform-webworker</code> and<code class="markup--code markup--li-code">@angular/platform-webworker-dynamic</code> both the packages are deprecated</li><li name="ba4b" class="graf graf--li graf-after--li">Usage for any in TesBed.get</li><li name="da8c" class="graf graf--li graf-after--li">Removed deprecated DOCUMENT from <code class="markup--code markup--li-code">@angular/platform-browser</code></li><li name="081c" class="graf graf--li graf-after--li">@angular/http removed from the list of packages</li><li name="c8d4" class="graf graf--li graf-after--li">ngForm element selector</li><li name="ba8d" class="graf graf--li graf-after--li">Service worker versionedFiles</li></ul><h3 name="3c08" class="graf graf--h3 graf-after--li">Angular Performance &amp; Upgradtion from Angular 7 to Angular&nbsp;8</h3><p name="883f" class="graf graf--p graf-after--h3">Angular 8 new features are nice, but the main reason for many of us to upgrade to new versions of Angular 8 is to get a performance boost. If you worked with previous angular versions then upgrading an app from Angular 7 over to Angular 8 is simple.</p><p name="eba6" class="graf graf--p graf-after--p">For most developers, one command should take care of this update&nbsp;:</p><pre name="0cb8" class="graf graf--pre graf-after--p">ng update @angular/cli @angular/core &lt;name&gt;</pre><h3 name="91dc" class="graf graf--h3 graf-after--pre">Angular Firebase</h3><p name="217a" class="graf graf--p graf-after--h3">Angular have officially added support for firebase and now we can deploy our application using the Angular CLI.</p><pre name="8801" class="graf graf--pre graf-after--p"><code class="markup--code markup--pre-code">ng run [PROJECT_NAME]:deploy</code></pre><h3 name="0974" class="graf graf--h3 graf-after--pre">Builders API</h3><p name="c50d" class="graf graf--p graf-after--h3">The new version allows us to use Builders API. It uses builders for main operations like: serve, build, test, lint and e2e. Basically, the builder Builders are functions that implement the logic and behavior for a task that can replace a command which you pass to the createBuilder() method from @angular-devkit/architect package &amp; now we can create our custom builders as well.</p><pre name="f988" class="graf graf--pre graf-after--p"><code class="markup--code markup--pre-code">import { BuilderOutput, createBuilder } from '@angular-devkit/architect';<br>export default createBuilder((options, context) =&gt; {<br>  return new Promise&lt;BuilderOutput&gt;(resolve =&gt; {<br>    resolve({ success: true });<br>  });<br>});</code></pre><h3 name="53c4" class="graf graf--h3 graf-after--pre">AngularJS API Migration Improvements with $location service</h3><p name="0c38" class="graf graf--p graf-after--h3">The Angular Team wants to provide support for all developers using AngularJS to upgrade them with latest Angular so some enhancements have been made to provide better integration with the AngularJS $location service in hybrid (AngularJS &lt;=&gt; Angular) apps. A new package <code class="markup--code markup--p-code">angular/common/upgrade</code> is added help you</p><ul class="postList"><li name="5bd4" class="graf graf--li graf-after--p">To retrieve the state from location service.</li><li name="4291" class="graf graf--li graf-after--li">To track all location changes.</li><li name="74af" class="graf graf--li graf-after--li">Help you retrieve hostname protocol port search properties which were available in AngularJS.</li><li name="e259" class="graf graf--li graf-after--li">MockPlatformLocation API added to test the location service.</li></ul><h3 name="9437" class="graf graf--h3 graf-after--li">Conclusion</h3><p name="61c8" class="graf graf--p graf-after--h3">Summing up all the above features, The Angular team has certainly did a great with the framework making developers job much easier &amp; simpler. Angular version 8 looks like a much more accessible solution focused on the modern technological trends added features like Ivy, route configurations use dynamic Imports, new builder API in the CLI, web worker support, Unified Angular Location Service &amp; with every new release, the framework is getting smoother and smoother making the Angular platform better.</p><h3 name="7f3f" class="graf graf--h3 graf-after--p">Next Steps</h3><p name="178a" class="graf graf--p graf-after--h3">Now that you have learnt the implementation of Firebase push notifications in Ionic 4, you can also try</p><ul class="postList"><li name="9f48" class="graf graf--li graf-after--p"><a href="https://enappd.com/blog/ionic-4-paypal-payment-integration-for-apps-and-pwa/16"  class="markup--anchor markup--li-anchor" rel="nofollow noopener noopener noopener noopener"    target="_blank">Ionic 4 PayPal payment integration&#8202;—&#8202;for Apps and PWA</a></li><li name="aa95" class="graf graf--li graf-after--li"><a href="https://enappd.com/blog/ionic-4-stripe-payment-integration-with-firebase-for-apps-and-pwa/17"  class="markup--anchor markup--li-anchor" rel="nofollow noopener noopener noopener noopener"    target="_blank">Ionic 4 Stripe payment integration&#8202;—&#8202;for Apps and PWA</a></li><li name="fc67" class="graf graf--li graf-after--li"><a href="https://enappd.com/blog/how-to-integrate-apple-pay-in-ionic-4-apps/21"  class="markup--anchor markup--li-anchor" rel="nofollow noopener noopener noopener noopener"    target="_blank">Ionic 4 Apple Pay integration</a></li><li name="b1fc" class="graf graf--li graf-after--li"><a href="https://enappd.com/blog/twitter-login-in-ionic-4-apps-using-firebase/24"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Twitter login in Ionic 4 with Firebase</a></li><li name="57fe" class="graf graf--li graf-after--li"><a href="https://enappd.com/blog/facebook-login-in-ionic-4-apps-using-firebase/25"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Facebook login in Ionic 4 with Firebase</a></li><li name="97f4" class="graf graf--li graf-after--li"><a href="https://medium.com/enappd/using-geolocation-and-beacon-plugins-in-ionic-4-754b41304007"  class="markup--anchor markup--li-anchor"    target="_blank">Geolocation</a> in Ionic 4</li><li name="34a6" class="graf graf--li graf-after--li"><a href="https://medium.com/enappd/qr-code-scanning-and-optical-character-recognition-ocr-in-ionic-4-95fd46be91dd"  class="markup--anchor markup--li-anchor"    target="_blank">QR Code and scanners</a> in Ionic 4 and</li><li name="de81" class="graf graf--li graf-after--li"><a href="https://medium.com/enappd/how-to-translate-in-ionic-4-globalization-internationalization-and-localization-31ec5807a8bc"  class="markup--anchor markup--li-anchor"    target="_blank">Translations in Ionic 4</a></li></ul><p name="2930" class="graf graf--p graf-after--li">If you need a base to start your next Ionic 4 app, you can make your next awesome app using <a href="https://store.enappd.com/product/ionic-4-full-app/"  class="markup--anchor markup--p-anchor" rel="noopener nofollow noopener noopener nofollow noopener noopener nofollow noopener noopener noopener noopener"    target="_blank">Ionic 4 Full App</a></p><figure tabindex="0" contenteditable="false" name="89dc" class="graf graf--figure graf-after--p is-defaultValue"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 442px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 63.2%;"></div><img class="graf-image" data-image-id="1*2BzL8TesnBHuazHr3VA4SQ.jpeg" data-width="760" data-height="480" src="https://cdn-images-1.medium.com/max/600/1*2BzL8TesnBHuazHr3VA4SQ.jpeg"><div class="crosshair u-ignoreBlock"></div></div></figure><p name="96c4" class="graf graf--p graf--empty graf-after--figure graf--trailing"><br></p></div></div></section></div></article></main>