{"id":7499,"date":"2024-12-12T11:26:36","date_gmt":"2024-12-12T10:26:36","guid":{"rendered":"https:\/\/blog.bart.sk\/en\/?p=7499"},"modified":"2024-12-12T11:26:37","modified_gmt":"2024-12-12T10:26:37","slug":"zoneless-in-practice-how-to-take-control-of-your-angular-application","status":"publish","type":"post","link":"https:\/\/blog.bart.sk\/en\/zoneless-in-practice-how-to-take-control-of-your-angular-application\/","title":{"rendered":"Zoneless in Practice: How to Take Control of Your Angular Application"},"content":{"rendered":"\n<h2 class=\"wp-block-heading has-medium-font-size\"><strong>In this series, you will learn:<\/strong><\/h2>\n\n\n\n<ol class=\"wp-block-list has-layout-background-color has-background\">\n<li><a href=\"https:\/\/blog.bart.sk\/en\/step-into-the-world-of-zoneless-programming\/\" target=\"_blank\" rel=\"noreferrer noopener\">Why Start with Zoneless Programming?<\/a><\/li>\n\n\n\n<li><strong>How to Remove Dependencies on Zone.js and Introduce Signals in Your Angular Project<\/strong><\/li>\n\n\n\n<li>Advanced Zoneless Angular Principles: Signals, Effects, and New Opportunities<\/li>\n\n\n\n<li>How to Properly Optimize a Zoneless Project and Monitor Its Performance<\/li>\n\n\n\n<li>Tips, Tricks, and the Future of Zoneless Angular: Real-World Examples<\/li>\n<\/ol>\n\n\n\n<p><strong>In the previous blog, we explored why it\u2019s worth diving into zoneless programming in Angular and the benefits of removing the <kbd>Zone.js<\/kbd> dependency. Now it\u2019s time to move from theory to practice. We\u2019ll guide you through the concrete steps to successfully migrate your project to a zoneless architecture. We\u2019ll focus on practical tools to ease the transition and demonstrate how to implement manual change detection effectively using signals.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Preparing for the Transition<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>New Projects<\/strong><\/h3>\n\n\n\n<p>If you\u2019re starting a new project, you have the advantage of implementing a zoneless architecture from the ground up. <strong>Simply call <kbd>provideExperimentalZonelessChangeDetection()<\/kbd> in the application root:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/blog.bart.sk\/wp-content\/uploads\/2024\/12\/code_20241212_111751_via_10015_io.png\" alt=\"\" class=\"wp-image-12990\"\/><\/figure>\n\n\n\n<p><em>Note: The <kbd>provideExperimentalZonelessChangeDetection<\/kbd> feature is currently marked as experimental (flagged as native experimental) and may be modified or removed after stabilization.<\/em><\/p>\n\n\n\n<p>Next, remove <kbd>Zone.js<\/kbd> from <strong>polyfills.ts<\/strong>, <strong>angular.json<\/strong>, and <strong>package.json<\/strong>. <strong>This creates a clean environment free of unnecessary dependencies<\/strong>, leading to smaller application size, faster load times, and overall better performance.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Existing Projects<\/h3>\n\n\n\n<p>If you already have a working application, it\u2019s not advisable to remove <kbd>Zone.js<\/kbd> immediately. <strong>It\u2019s better to take a gradual approach, starting by setting the following for each component:<\/strong><br><br><kbd><strong>changeDetection: ChangeDetectionStrategy.OnPush<\/strong><\/kbd><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>This strategy <strong>minimizes component rendering triggered by global changes<\/strong>.<\/li>\n\n\n\n<li><strong>Use:&nbsp;<\/strong>\n<ul class=\"wp-block-list\">\n<li><strong><kbd>markForCheck()<\/kbd><\/strong>: To schedule a component re-render with OnPush. This <strong>performance-friendly approach<\/strong> allows for efficient change management.<\/li>\n\n\n\n<li><strong><kbd>detectChanges()<\/kbd><\/strong>: To trigger immediate change detection and rendering during a method or function. Use cautiously, as <strong>it can negatively impact application performance.<\/strong><\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<p>This change management process requires manual intervention. <strong>Fortunately, signals effectively replace this need.<\/strong> Signals &#8220;listen&#8221; to emitted values and allow Angular to automatically update templates based on value changes.<\/p>\n\n\n\n<p><strong>OnPush ensures that rendering responds only to signal changes or, in rare cases, manual <kbd>markForCheck<\/kbd> calls, avoiding unnecessary interference from other processes.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Signals: Smart Change Management<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>What Are Signals?<\/strong><\/h3>\n\n\n\n<p>Signals introduce an automated dependency system between data and their tracking. <strong>They create a dependency tree efficiently managed by Angular.<\/strong> Signals can be:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Read-only:<\/strong> For value tracking.<\/li>\n\n\n\n<li><strong>Writable:<\/strong> For value updates.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Creating a Writable Signal<\/strong><\/h4>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/blog.bart.sk\/wp-content\/uploads\/2024\/12\/code_20241212_111921_via_10015_io.png\" alt=\"\" class=\"wp-image-12991\"\/><\/figure>\n\n\n\n<p><strong>WritableSignal also offers a useful method, <kbd>asReadonly()<\/kbd>, to convert a Writable signal into a regular read-only signal.<\/strong> This ensures the signal serves as a value producer without direct modifications outside its primary context.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Using <kbd>computed<\/kbd>: Automating Derived Values<\/strong><\/h3>\n\n\n\n<p><strong><kbd>Computed<\/kbd> signals are a special type of read-only signals that dynamically calculate their value based on dependencies defined in their logic.<\/strong> Their key advantage is automatic dependency tracking and value updates, eliminating the need for manual updates or dependency management.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Usage Example<\/strong><\/h4>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/blog.bart.sk\/wp-content\/uploads\/2024\/12\/code_20241211_083134_via_10015_io.png\" alt=\"\" class=\"wp-image-12958\"\/><\/figure>\n\n\n\n<p>In this example:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><kbd><strong>showCount<\/strong><\/kbd> determines whether the <kbd>count<\/kbd> value should be displayed.<\/li>\n\n\n\n<li><strong><kbd>conditionalCount<\/kbd><\/strong> is a <kbd>computed<\/kbd> signal that reacts only to changes in the <kbd>showCount<\/kbd> or <kbd>count<\/kbd> signals, but only when necessary.<\/li>\n<\/ol>\n\n\n\n<p><strong><kbd>Computed<\/kbd> signals have specific properties:<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Dynamic dependencies:<\/strong> When <kbd>conditionalCount<\/kbd> is first used, its function body runs, and dependencies are automatically &#8220;calculated.&#8221; For example, <kbd>conditionalCount<\/kbd> depends on <kbd>showCount<\/kbd>. If <kbd>count<\/kbd> changes, <kbd>computed<\/kbd> won\u2019t trigger unless <kbd>count<\/kbd> was activated as a dependency.<\/li>\n\n\n\n<li><strong>Lazy evaluation:<\/strong> The <kbd>computed<\/kbd> function executes only when its result is actually used. If <kbd>conditionalCount<\/kbd> is never called, its derivation function doesn\u2019t run.<\/li>\n\n\n\n<li><strong>Dynamic dependency reconfiguration:<\/strong> If <kbd>showCount<\/kbd> changes to <kbd>true<\/kbd>, <kbd>computed<\/kbd> recalculates its function and adds <kbd>count<\/kbd> as a dependency as needed. This process is automatic and updates dependencies dynamically.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Hidden Tricks of <kbd>computed<\/kbd><\/strong><\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Dependencies on other <kbd>computed<\/kbd> signals:<\/strong> Computed signals can depend on other <kbd>computed<\/kbd> signals. Since every signal produces a value, <kbd>computed<\/kbd> signals can be chained, enabling complex derivations without manual dependency tracking.<\/li>\n\n\n\n<li><strong>Immutable from the outside:<\/strong> <kbd>computed<\/kbd> signals cannot be directly modified. They are designed for value derivation, preventing unintended changes. However, Angular plans to introduce mixed producers like <kbd>linkedSignal<\/kbd>, introduced in Angular 19, in the future.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Using Effects: Automating Specific Scenarios<\/strong><\/h3>\n\n\n\n<p><strong>Angular also introduces the concept of effects (<kbd>effect<\/kbd>) within signals, enabling tracking and executing actions based on changes.<\/strong> Effects are particularly useful for scenarios where you need to react to signal value changes without affecting application state:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Example of Using an Effect:<\/strong><\/h4>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/blog.bart.sk\/wp-content\/uploads\/2024\/12\/code_20241211_083147_via_10015_io.png\" alt=\"\" class=\"wp-image-12959\"\/><\/figure>\n\n\n\n<p>Effects are helpful for various tasks such as:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Writing to the <strong>DOM<\/strong> or <strong>localStorage<\/strong>.<\/li>\n\n\n\n<li>Triggering side effects without modifying state.<\/li>\n\n\n\n<li>Automatically tracking changes without manual checks.<\/li>\n<\/ul>\n\n\n\n<p>Effects complement signals, <kbd>computed<\/kbd> logic, and manual change management, creating a comprehensive and flexible architecture for modern Angular applications.<\/p>\n\n\n\n<p class=\"has-layout-background-color has-background\"><strong><em>Migrating to a zoneless architecture is more than just removing <kbd>Zone.js<\/kbd>. It\u2019s a new way of thinking, giving you control over when and where rendering occurs within the application.&nbsp;<\/em><\/strong><\/p>\n\n\n\n<p>Signals, together with computed logic and effects, create a robust architecture that minimizes the need for manual change management, enabling faster and more efficient development.<\/p>\n\n\n\n<p><strong>In the next part, we\u2019ll dive into advanced concepts, such as transformations between signals and observables, handling destroyed components and contexts, and leveraging signals for even more efficient architecture.<\/strong><\/p>\n\n\n\n<p>If you\u2019re already intrigued by what signals can offer, know that this is just the beginning.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-text-align-center\">Interested in development? You might enjoy more articles on this topic!<\/h2>\n\n\n\n<div class=\"wp-block-buttons is-content-justification-center is-layout-flex wp-container-core-buttons-layout-1 wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/blog.bart.sk\/en\/category\/development\/\" target=\"_blank\" rel=\"noreferrer noopener\">I Want to Read More<\/a><\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"In this series, you will learn: In the previous blog, we explored why it\u2019s worth diving into zoneless&hellip;","protected":false},"author":17,"featured_media":7500,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","csco_display_header_overlay":false,"csco_singular_sidebar":"","csco_page_header_type":""},"categories":[199],"tags":[146,608,607,606,599],"_links":{"self":[{"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/posts\/7499"}],"collection":[{"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/users\/17"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/comments?post=7499"}],"version-history":[{"count":1,"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/posts\/7499\/revisions"}],"predecessor-version":[{"id":7503,"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/posts\/7499\/revisions\/7503"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/media\/7500"}],"wp:attachment":[{"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/media?parent=7499"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/categories?post=7499"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.bart.sk\/en\/wp-json\/wp\/v2\/tags?post=7499"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}