{"id":25969,"date":"2024-06-26T14:24:31","date_gmt":"2024-06-26T12:24:31","guid":{"rendered":"https:\/\/www.angulararchitects.io\/blog\/whats-new-in-angular-18\/"},"modified":"2024-06-26T15:09:43","modified_gmt":"2024-06-26T13:09:43","slug":"whats-new-in-angular-18","status":"publish","type":"post","link":"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/","title":{"rendered":"What&#8217;s new in Angular 18?"},"content":{"rendered":"<p>In May 2024, the Angular team released version 18 of its framework. For the first time, it offers an official way to work without Zone.js, albeit only experimentally. There are also some really nice improvements in existing API such as the router. <\/p>\n<p>In this article I will discuss the new features. <\/p>\n<p>\ud83d\udcc2 <a href=\"https:\/\/github.com\/manfredsteyer\/hero-shop.git\">Source Code<\/a><\/p>\n<h2>Zone-less<\/h2>\n<p>Since its early days, Angular has used the Zone.js library to figure out when change detection needs to check the component tree for changes. The idea behind it is simple: in a JavaScript application, only event handlers can change bound data. So the goal is to figure out when an event handler has been executed. To do this, Zone.js hooks into all browser objects: <em>HTMLInputElement<\/em>, <em>Promise<\/em>, and <em>XmlHttpRequest<\/em> are just a few examples. This approach, which uses the dynamic nature of JavaScript to change existing objects, is called monkey patching.<\/p>\n<p>Even if this approach usually works well, it does lead to problems. For example, bugs in this area are difficult to diagnose and since not every event handler necessarily changes bound data, change detection runs too frequently. If you develop reusable web components that hide implementation details such as the use of Angular, the consumer still has to use them with a specific Zone.js version.<\/p>\n<p>As of version 18, the framework now also supports a data binding mode that does not require Zone.js. It is experimental for now so that the Angular team can collect feedback on the new approach. To enable this mode, the <em>provideExperimentalZonelessChangeDetection<\/em> function must be used when bootstrapping the application:<\/p>\n<pre><code class=\"language-typescript\">export const appConfig: ApplicationConfig = {\n  providers: [\n    provideExperimentalZonelessChangeDetection(),\n    [\u2026]\n  ]\n}<\/code><\/pre>\n<p>Since Zone.js no longer triggers change detection, Angular needs other triggers. These are the ones that are also used in the <em>OnPush<\/em> data binding mode:<\/p>\n<ul>\n<li>An observable bound with the <em>async<\/em> pipe publishes a new value.<\/li>\n<li>A bound signal publishes a new value.<\/li>\n<li>The object reference of an input changes.<\/li>\n<li>A UI event with a bound event handler occurs (e.g. <em>click<\/em>).<\/li>\n<li>The application triggers the change detection manually.<\/li>\n<\/ul>\n<p>This means that those who have consistently used <em>OnPush<\/em> in the past can now switch to Zone-less with relative ease. In cases where this is not easily possible, the application can remain Zone.js-based without any concerns. The Angular team assumes that not every existing application will be switched to Zone-less and therefore continues to support Zone.js.<\/p>\n<p>However, for new applications, it is advisable to work without Zone.js as soon as this new mode is no longer experimental. The planned Signal Components will make Zone-less applications easier in the future, as they automatically meet the requirements through the consistent use of Signals.<\/p>\n<p>After switching to Zone-less, the reference to Zone.js can also be removed from the <em>angular.json<\/em> . By removing this library, the bundles in production mode become about 11 KB smaller.<\/p>\n<h2>Coalescing Zone<\/h2>\n<p>For new applications, the Angular CLI still uses Zone.js. What's new is that it now generates code that enables event coalescing by default:<\/p>\n<pre><code class=\"language-typescript\">export const appConfig: ApplicationConfig = {\n  providers: [\n    provideZoneChangeDetection({ eventCoalescing: true }),\n    [\u2026]\n  ]\n};<\/code><\/pre>\n<p>Event coalescing means that Zone.js only takes action once for events that occur immediately after each other. The Angular team gives an example of several click handlers that are triggered one after the other due to event bubbling.<\/p>\n<h2>Modern Angular<\/h2>\n<p><a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/\"><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/04\/sujet-de.jpg\" style=\"max-width:500px\"><\/a><\/p>\n<p>Update your Angular knowledge with our <a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/\">Modern Angular Workshop<\/a> (<a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/\">Englisch Version<\/a>, <a href=\"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/\">German Version<\/a>)<\/p>\n<h2>New Features in Router Redirects<\/h2>\n<p>If a guard wants to redirect to another route, it returns the <em>UrlTree<\/em> of this route. Unlike the <em>navigate<\/em> method, however, this approach does not allow the specification of options for detailed control of the router's behavior. For example, the application cannot specify whether the current entry in the browser history is to be overwritten or whether parameters that should not appear in the URL are to be passed.<\/p>\n<p>To use this option, a guard can now also return a <em>RedirectCommand<\/em>. In addition to the <em>UrlTree<\/em>, this <em>RedirectCommand<\/em> receives an object of type <em>NavigationBehaviorOptions<\/em> that controls the desired behavior:<\/p>\n<pre><code class=\"language-typescript\">export function isAuth(destination: ActivatedRouteSnapshot) {\n    const router = inject(Router);\n    const auth = inject(AuthService);\n\n    if (auth.isAuth()) {\n        return true;\n    }\n\n    const afterLoginRedirect = destination.url.join(&#039;\/&#039;);\n    const urlTree = router.parseUrl(&#039;\/login&#039;);\n\n    return new RedirectCommand(urlTree, {\n        skipLocationChange: true,\n        state: {\n            needsLogin: true,\n            afterLoginRedirect: afterLoginRedirect\n        } as RedirectToLoginState,\n    });\n}\n\nexport const routes: Routes = [\n    {\n        path: &#039;&#039;,\n        redirectTo: &#039;products&#039;,\n        pathMatch: &#039;full&#039;\n    },\n    {\n        path: &#039;products&#039;,\n        component: ProductListComponent,\n    },\n    {\n        path: &#039;login&#039;,\n        component: LoginComponent,\n    },\n    {\n        path: &#039;products\/:id&#039;,\n        component: ProductDetailComponent,\n        canActivate: [isAuth]\n    },\n    {\n        path: &#039;error&#039;,\n        component: ErrorComponent\n    }\n];<\/code><\/pre>\n<p>The <em>skipLocationChange<\/em> property specifies that the route change should not appear in the browser history and the specified <em>state<\/em> contains values that are to be passed to the component to be activated, but should not appear in the URL. <a href=\"https:\/\/angular.dev\/api\/router\/NavigationBehaviorOptions\">Further properties<\/a> provided by <em>NavigationBehaviorOptions<\/em> can be found <a href=\"https:\/\/angular.dev\/api\/router\/NavigationBehaviorOptions\">here<\/a>.<\/p>\n<p>For the sake of completeness, the following listing shows the addressed component that reads the passed data:<\/p>\n<pre><code class=\"language-typescript\">@Component({ \u2026 })\nexport class LoginComponent {\n  router = inject(Router);\n  auth = inject(AuthService);\n\n  state: RedirectToLoginState | undefined;\n\n  constructor() {\n    const nav = this.router.getCurrentNavigation();\n\n    if (nav?.extras.state) {\n      this.state = nav?.extras.state as RedirectToLoginState;\n    }\n  }\n\n  logout() {\n    this.auth.logout();\n  }\n\n  login() {\n    this.auth.login(&#039;John&#039;);\n    if (this.state?.afterLoginRedirect) {\n      this.router.navigateByUrl(this.state?.afterLoginRedirect);\n    }\n  }\n\n}<\/code><\/pre>\n<p>The use of a <em>RedirectCommand<\/em> is now also supported by the optional feature <em>withNavigationErrorHandler<\/em>:<\/p>\n<pre><code class=\"language-typescript\">export function handleNavError(error: NavigationError) {\n  console.log(&#039;error&#039;, error);\n\n  const router = inject(Router);\n  const urlTree = router.parseUrl(&#039;\/error&#039;)\n  return new RedirectCommand(urlTree, {\n    state: {\n      error\n    }\n  })\n}\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    [\u2026]\n    provideRouter(\n      routes,\n      withComponentInputBinding(),\n      withViewTransitions(),\n      withNavigationErrorHandler(handleNavError),\n    ),\n  ]\n};<\/code><\/pre>\n<p>Another new feature in terms of redirects concerns the <em>redirectTo<\/em> property in the router configuration. Until now, you could refer to the name of another route. Now this property also accepts a function that takes care of the redirection programmatically:<\/p>\n<pre><code class=\"language-typescript\">export const routes: Routes = [\n    {\n        path: &#039;&#039;,\n        redirectTo: () =&gt; {\n            const router = inject(Router);\n            \/\/ return &#039;products&#039; \/\/ Alternative\n            return router.parseUrl(&#039;\/products&#039;);\n        },\n        pathMatch: &#039;full&#039;\n    },\n    [\u2026],\n];<\/code><\/pre>\n<p>The return value of this function is either a <em>UrlTree<\/em> or a <em>string<\/em> with the path of the desired route.<\/p>\n<h2>Standard Content for Content Projection<\/h2>\n<p>The <em>ng-content<\/em> element used as a target for content projection can now have default content. This is the content that Angular displays if the caller does not pass any other content:<\/p>\n<pre><code class=\"language-html\">&lt;div class=&quot;pl-10 mb-20&quot;&gt;\n    &lt;ng-content&gt;\n        &lt;b&gt;Book today to get 5% discount!&lt;\/b&gt;\n    &lt;\/ng-content&gt;\n&lt;\/div&gt;<\/code><\/pre>\n<h2>Events for Reactive Forms<\/h2>\n<p>The <em>AbstractControl<\/em>, which acts as a base class for <em>FormControl<\/em>, <em>FormGroup<\/em>, and others, now has an <em>events<\/em> property. This Observable informs about numerous state changes:<\/p>\n<pre><code class=\"language-typescript\">export class ProductDetailComponent implements OnChanges {\n\n  [\u2026]\n\n  formControl = new FormControl&lt;number&gt;(1);\n\n  [\u2026] \n\n  constructor() {\n    this.formControl.events.subscribe(e =&gt; {\n      console.log(&#039;e&#039;, e);\n    });\n  }\n\n  [\u2026]\n\n}<\/code><\/pre>\n<p>It publishes the individual events as objects of type <em>ControlEvent<\/em>. <em>ControlEvent<\/em> is an abstract base class with the following implementations:<\/p>\n<ul>\n<li><em>FormResetEvent<\/em><\/li>\n<li><em>FormSubmittedEvent<\/em><\/li>\n<li><em>PristineChangeEvent<\/em><\/li>\n<li><em>StatusChangeEvent<\/em><\/li>\n<li><em>TouchedChangeEvent<\/em><\/li>\n<li><em>ValueChangeEvent<\/em><\/li>\n<\/ul>\n<h2>Event Replay for SSR<\/h2>\n<p>By using server-side rendering, the requested page is displayed to the user more quickly. The browser then begins loading the JavaScript bundles that make the page interactive, also known as hydration: <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/06\/Server-Side-Rendering.png\" alt=\"Uncanny Valley at SSR\" \/><\/p>\n<p>Here, FMP stands for First Meaningful Paint and TTI for Time to Interactive. <\/p>\n<p>The time span between FMP and TTI, also known as the &quot;uncanny valley&quot;, requires special attention. The user is already shown the page here. However, the JavaScript that reacts to user interactions has not yet been loaded. Clicks and other interactions are therefore ignored.<\/p>\n<p>To prevent this, Angular now offers an event replay that records the interactions in the uncanny valley and then repeats them. This is made possible by a minimal script that the browser initially loads together with the pre-rendered page.<\/p>\n<p>Event Replay comes as an optional feature for <em>provideClientHydration<\/em> and is activated with the <em>withEventReplay<\/em> function:<\/p>\n<pre><code class=\"language-typescript\">export const appConfig: ApplicationConfig = {\n  providers: [\n    [\u2026],\n    provideClientHydration(\n      withEventReplay()\n    )\n  ]\n};<\/code><\/pre>\n<p>The implementation of Event Replay has been proven at Google for some time. It comes from Google's internal framework Wiz <a href=\"https:\/\/blog.angular.dev\/angular-and-wiz-are-better-together-91e633d8cd5a\">Wiz<\/a>, which is known for its capabilities in the areas of SSR and hydration and is therefore used for performance-critical public solutions.<\/p>\n<p>At this year's ng-conf, the Angular team announced that the Angular and Wiz teams will be working more closely together in the future. In a first step, the Wiz team will use Angular's Signals, while Angular has adopted the tried and tested event replay options from the Wiz team.<\/p>\n<h2>Automatic TransferState for HTTP Requests<\/h2>\n<p>When using SSR, the <em>HttpClient<\/em> caches the results of HTTP requests made on the server side so that the requests do not have to be executed again in the browser. An interceptor delegating to the Transfer State API is used for this. The Transfer API embeds the cached data in the markup of the pre-rendered page and the <em>HttpClient<\/em> accesses it in the browser.<\/p>\n<p>This implementation now also takes into account that different URLs can be used on the server side than in the browser. For this purpose, an object can be configured that maps internal server-side URLs to the URLs for use in the browser. The following example from respective <a href=\"https:\/\/github.com\/angular\/angular\/pull\/55274\">pull request<\/a> illustrates the configuration of this object:<\/p>\n<pre><code class=\"language-typescript\">\/\/ in app.server.config.ts\n{\n    provide: HTTP_TRANSFER_CACHE_ORIGIN_MAP,\n    useValue: {\n        &#039;http:\/\/internal-domain:80&#039;: &#039;https:\/\/external-domain:443&#039;\n    }\n}\n\n\/\/ Alternative usage with dynamic values \n    \/\/ (depending on stage or prod environments)\n{\n    provide: HTTP_TRANSFER_CACHE_ORIGIN_MAP,\n    useFactory: () =&gt; {\n        const config = inject(ConfigService);\n        return {\n            [config.internalOrigin]: [config.externalOrigin],\n        };\n    }\n}<\/code><\/pre>\n<p><em>HttpClient<\/em> no longer automatically places the results of server-side HTTP requests that contain an <em>Authorization<\/em> or <em>Proxy-Authorization<\/em> header in the Transfer State. If you want to continue to cache such results in the future, use the new <em>includeRequestsWithAuthHeaders<\/em> property:<\/p>\n<pre><code class=\"language-typescript\">withHttpTransferCache({\n  includeRequestsWithAuthHeaders: true,\n})<\/code><\/pre>\n<h2>DevTools and Hydration<\/h2>\n<p>If desired, the Angular DevTools now show which components have already been hydrated. To do this, activate the <em>Show hydration overlays<\/em> option at the bottom right:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/06\/hydration-dev-tools.png\" alt=\"The DevTools now show which components have already been hydrated\" \/><\/p>\n<p>This option displays all hydrated components with a blue-transparent overlay and a water drop icon in the top right.<\/p>\n<h2>Migration to new ApplicationBuilder<\/h2>\n<p>The new <em>ApplicationBuilder<\/em> was introduced with Angular 17 and automatically set up for new Angular applications. Since it is based on modern technologies such as esbuild, it is much faster than the original webpack-based builder, which Angular still supports. In initial tests, I was able to see an acceleration of a factor of 3 to 4. The <em>ApplicationBuilder<\/em> also comes with convenient support for SSR.<\/p>\n<p>When updating to Angular 18, the CLI now suggests converting existing applications to the ApplicationBuilder:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/06\/migrate.png\" alt=\"When updating to version 18 you get the option to migrate to the new ApplicationBuilder\" \/><\/p>\n<p>Since the CLI team has invested a lot of effort in feature parity between the classic and the new implementation, this change should work well in most cases and speed up build times dramatically.<\/p>\n<h2>Further Innovations<\/h2>\n<p>In addition to the new features already described, there are some smaller updates and improvements:<\/p>\n<ul>\n<li><em>@defer<\/em> also works in npm packages.<\/li>\n<li>A new token _HOST_TAG<em>NAME<\/em> points to the tag name of the current component.<\/li>\n<li>Angular I18N now works with Hydration.<\/li>\n<li>The modules <em>HttpClientModule<\/em>, <em>HttpClientXsrfModule<\/em>, and <em>HttpClientJsonpModule<\/em> as well as the <em>HttpClientTestingModule<\/em> are now deprecated. The corresponding standalone APIs such as <em>provideHttpClient<\/em> are used as replacements. A schematic automatically takes care of this change when updating to Angular 18.<\/li>\n<li>For new projects, the CLI now sets up a <em>public<\/em> folder instead of an <em>assets<\/em> folder. With this, the Angular team wants to move closer to a common practice in the world of web development.<\/li>\n<li>For Zone-less applications, the CLI no longer converts <em>async<\/em> and <em>await<\/em> to promises. This is necessary when using Zone.js because, other than <em>async<\/em> and <em>await<\/em>, Promises can be monkey-patched.<\/li>\n<li>The <em>ApplicationBuilder<\/em> now caches intermediate results. This can dramatically speed up subsequent builds.<\/li>\n<\/ul>\n<h2>What's next? Modern Angular!<\/h2>\n<p>Modern Angular has even more to offer:<\/p>\n<ul>\n<li>Reactive data flows with Signals<\/li>\n<li>Updated APIs for the Router and HttpClient<\/li>\n<li>Standalone Components, Directives, and Pipes<\/li>\n<li>The new built-in control flow and @defer<\/li>\n<li>Options for automatic migrations<\/li>\n<li>esbuild, SSR, and Hydration<\/li>\n<\/ul>\n<p>In our free eBook, we cover these topics in 14 chapters. Download it now:<\/p>\n<p><a href=\"https:\/\/www.angulararchitects.io\/en\/ebooks\/modern-angular\/\"><img decoding=\"async\" src=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/04\/cover-1.png\" style=\"max-width: 400px\"><\/a><\/p>\n<p>[<a href=\"https:\/\/www.angulararchitects.io\/en\/ebooks\/modern-angular\/\">Download now!<\/a>]<\/p>\n<h2>Summary<\/h2>\n<p>After several releases with many new features, Angular 18 focuses primarily on rounding corners. There are new options for router redirects, default values for content projection, event replay and improvements for using the Transfer State API for HTTP requests. <\/p>\n<p>In addition, numerous bugs have been addressed and the performance of the new <em>ApplicationBuilder<\/em> has been improved through caching. Besides this, there also a preview of Zone-less Angular that will pave the way for the future of the framework's change detection.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In May 2024, the Angular team released version 18 of its framework. For the first time, it offers an official way to work without Zone.js, albeit only experimentally. There are also some really nice improvements in existing API such as the router. In this article I will discuss the new features. \ud83d\udcc2 Source Code Zone-less [&hellip;]<\/p>\n","protected":false},"author":25,"featured_media":25963,"comment_status":"open","ping_status":"open","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-25969","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>What&#039;s new in Angular 18? - 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\/blog\/whats-new-in-angular-18\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"What&#039;s new in Angular 18? - ANGULARarchitects\" \/>\n<meta property=\"og:description\" content=\"In May 2024, the Angular team released version 18 of its framework. For the first time, it offers an official way to work without Zone.js, albeit only experimentally. There are also some really nice improvements in existing API such as the router. In this article I will discuss the new features. \ud83d\udcc2 Source Code Zone-less [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/\" \/>\n<meta property=\"og:site_name\" content=\"ANGULARarchitects\" \/>\n<meta property=\"article:published_time\" content=\"2024-06-26T12:24:31+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-06-26T13:09:43+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/06\/ng18.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1001\" \/>\n\t<meta property=\"og:image:height\" content=\"563\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Manfred Steyer\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/06\/ng18.jpg\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Manfred Steyer\" \/>\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\/blog\/whats-new-in-angular-18\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/\"},\"author\":{\"name\":\"Manfred Steyer\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/f3de69c1e2bdb5ba04d8d2f5f998b81a\"},\"headline\":\"What&#8217;s new in Angular 18?\",\"datePublished\":\"2024-06-26T12:24:31+00:00\",\"dateModified\":\"2024-06-26T13:09:43+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/\"},\"wordCount\":1752,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/06\/shutterstock_2409568271.jpg\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/\",\"url\":\"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/\",\"name\":\"What's new in Angular 18? - ANGULARarchitects\",\"isPartOf\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/06\/shutterstock_2409568271.jpg\",\"datePublished\":\"2024-06-26T12:24:31+00:00\",\"dateModified\":\"2024-06-26T13:09:43+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/#primaryimage\",\"url\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/06\/shutterstock_2409568271.jpg\",\"contentUrl\":\"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/06\/shutterstock_2409568271.jpg\",\"width\":1000,\"height\":667},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.angulararchitects.io\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"What&#8217;s new in Angular 18?\"}]},{\"@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\/f3de69c1e2bdb5ba04d8d2f5f998b81a\",\"name\":\"Manfred Steyer\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/8778dfb353992fa3a0d909beee085a088891e5bfce65cdb3631801da527cf11b?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/8778dfb353992fa3a0d909beee085a088891e5bfce65cdb3631801da527cf11b?s=96&d=mm&r=g\",\"caption\":\"Manfred Steyer\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"What's new in Angular 18? - 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\/blog\/whats-new-in-angular-18\/","og_locale":"en_US","og_type":"article","og_title":"What's new in Angular 18? - ANGULARarchitects","og_description":"In May 2024, the Angular team released version 18 of its framework. For the first time, it offers an official way to work without Zone.js, albeit only experimentally. There are also some really nice improvements in existing API such as the router. In this article I will discuss the new features. \ud83d\udcc2 Source Code Zone-less [&hellip;]","og_url":"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/","og_site_name":"ANGULARarchitects","article_published_time":"2024-06-26T12:24:31+00:00","article_modified_time":"2024-06-26T13:09:43+00:00","og_image":[{"width":1001,"height":563,"url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/06\/ng18.jpg","type":"image\/jpeg"}],"author":"Manfred Steyer","twitter_card":"summary_large_image","twitter_image":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/06\/ng18.jpg","twitter_misc":{"Written by":"Manfred Steyer","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/#article","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/"},"author":{"name":"Manfred Steyer","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/f3de69c1e2bdb5ba04d8d2f5f998b81a"},"headline":"What&#8217;s new in Angular 18?","datePublished":"2024-06-26T12:24:31+00:00","dateModified":"2024-06-26T13:09:43+00:00","mainEntityOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/"},"wordCount":1752,"commentCount":0,"publisher":{"@id":"https:\/\/www.angulararchitects.io\/en\/#organization"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/06\/shutterstock_2409568271.jpg","inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/","url":"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/","name":"What's new in Angular 18? - ANGULARarchitects","isPartOf":{"@id":"https:\/\/www.angulararchitects.io\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/#primaryimage"},"image":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/#primaryimage"},"thumbnailUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/06\/shutterstock_2409568271.jpg","datePublished":"2024-06-26T12:24:31+00:00","dateModified":"2024-06-26T13:09:43+00:00","breadcrumb":{"@id":"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/#primaryimage","url":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/06\/shutterstock_2409568271.jpg","contentUrl":"https:\/\/www.angulararchitects.io\/wp-content\/uploads\/2024\/06\/shutterstock_2409568271.jpg","width":1000,"height":667},{"@type":"BreadcrumbList","@id":"https:\/\/www.angulararchitects.io\/en\/blog\/whats-new-in-angular-18\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.angulararchitects.io\/en\/"},{"@type":"ListItem","position":2,"name":"What&#8217;s new in Angular 18?"}]},{"@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\/f3de69c1e2bdb5ba04d8d2f5f998b81a","name":"Manfred Steyer","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.angulararchitects.io\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/8778dfb353992fa3a0d909beee085a088891e5bfce65cdb3631801da527cf11b?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/8778dfb353992fa3a0d909beee085a088891e5bfce65cdb3631801da527cf11b?s=96&d=mm&r=g","caption":"Manfred Steyer"}}]}},"_links":{"self":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/25969","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\/25"}],"replies":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/comments?post=25969"}],"version-history":[{"count":2,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/25969\/revisions"}],"predecessor-version":[{"id":25972,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/posts\/25969\/revisions\/25972"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media\/25963"}],"wp:attachment":[{"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/media?parent=25969"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/categories?post=25969"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.angulararchitects.io\/en\/wp-json\/wp\/v2\/tags?post=25969"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}