mirror of
https://github.com/Raghu-Ch/angular-challenges.git
synced 2026-02-10 04:43:03 -05:00
feat(challenge35): memoization performance
This commit is contained in:
@@ -1,24 +1,3 @@
|
|||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
> Thank you for considering contributing to this project. Your help is very much appreciated!
|
Learn how to contribute [here](https://angular-challenges.vercel.app/guides/contribute/)
|
||||||
|
|
||||||
When contributing, it's better to first explain the challenge/exercice you are thinking about in the issue tab.
|
|
||||||
|
|
||||||
## Getting started
|
|
||||||
|
|
||||||
Please follow those step in order to succesfully make your contribution to this repository.
|
|
||||||
|
|
||||||
1. Fork the project
|
|
||||||
2. Install **Nx Console**, this will help you work with this repository
|
|
||||||
3. Run `npm ci` to install all dependencies
|
|
||||||
4. Generate a new app with Nx Console > Right Click on apps folder > `Nx Generate Application`
|
|
||||||
5. Copy/Paste **example.README.md** and fill it up.
|
|
||||||
6. Link the main **README** with your new challenge
|
|
||||||
7. Few days later, create a PR with your answer.
|
|
||||||
8. Optional: write a blog post explaining your Challenge and the solution you came up with.
|
|
||||||
|
|
||||||
## Pull Request Process
|
|
||||||
|
|
||||||
1. We follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0-beta.4/)
|
|
||||||
in our commit messages, i.e. `feat(core): improve typing`
|
|
||||||
2. When you are ready, create Pull Request of your fork into original repository with the title starting with **NEW CHALLENGE**
|
|
||||||
|
|||||||
@@ -1,32 +1,13 @@
|
|||||||
<h1>memoized function</h1>
|
# Memoization
|
||||||
|
|
||||||
> Author: Thomas Laforge
|
> Author: Thomas Laforge
|
||||||
|
|
||||||
<!-- TODO: add Information/Statement/Rules/Constraint/Steps -->
|
### Run Application
|
||||||
|
|
||||||
## Information
|
```bash
|
||||||
|
npx nx serve performance-memoized
|
||||||
|
```
|
||||||
|
|
||||||
## Statement
|
### Documentation and Instruction
|
||||||
|
|
||||||
### Step 1
|
Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular-performance/35-memoize/).
|
||||||
|
|
||||||
### Step 2
|
|
||||||
|
|
||||||
### Constraints:
|
|
||||||
|
|
||||||
### Submitting your work
|
|
||||||
|
|
||||||
1. Fork the project
|
|
||||||
2. clone it
|
|
||||||
3. npm ci
|
|
||||||
4. `npx nx serve memoized`
|
|
||||||
5. _...work on it_
|
|
||||||
6. Commit your work
|
|
||||||
7. Submit a PR with a title beginning with **Answer:35** that I will review and other dev can review.
|
|
||||||
|
|
||||||
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A35+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="memoized"/></a>
|
|
||||||
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A35+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="memoized solution author"/></a>
|
|
||||||
|
|
||||||
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="memoized blog article"/></a> -->
|
|
||||||
|
|
||||||
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 129 KiB |
BIN
docs/src/assets/angular-performance/35/memoize-profiler.png
Normal file
BIN
docs/src/assets/angular-performance/35/memoize-profiler.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 87 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
@@ -5,32 +5,36 @@ sidebar:
|
|||||||
order: 12
|
order: 12
|
||||||
---
|
---
|
||||||
|
|
||||||
:::note
|
|
||||||
WIP: The following documentation will be reviewed and improved. However, you can still take on the challenge. If you don't understand a certain part, please feel free to reach out or create an issue.
|
|
||||||
:::
|
|
||||||
|
|
||||||
<div class="chip">Challenge #12</div>
|
<div class="chip">Challenge #12</div>
|
||||||
|
|
||||||
## Information
|
## Information
|
||||||
|
|
||||||
In this challenge, you will need to optimize the change detection cycles run by Angular.
|
In Angular, there is a library called <b>Zone.js</b> that performs a lot of magic to simplify a developer's life. Zone.js monkey patches all DOM events so that it will recheck and rerender the view when something has changed inside the application. The developer doesn't have to manually trigger change detection.
|
||||||
|
|
||||||
Zone.js triggers a change detection cycle each time a scroll event is dispatched. However we only want to show or hide a button at a specific scroll position. Therefore, we only want to refresh our application once.
|
However, sometimes Zone.js triggers a lot more change detection than needed. For example, when you are listening to a scroll event, each scroll event will dispatch a new change detection cycle.
|
||||||
|
|
||||||
> You can vizualise how many times CD is triggered by installing the [Angular chrome devTool](https://chrome.google.com/webstore/detail/angular-devtools/ienfalfjdbdpebioblfackkekamfmbnh) and starting a new recording on the profiler tab.
|
In this challenge, we only need to refresh the view at a specific scroll position to display or hide a button. All other cycles are unnecessary.
|
||||||
|
|
||||||
The following video will explain what is the goal of this challenge.
|
To have a better visualization of the problem, profile your application with Angular Dev Tools.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
If you don't know how to use it, read [the performance introduction page](/challenges/angular-performance/) first and come back after.
|
||||||
|
:::
|
||||||
|
|
||||||
|
You can learn more details about zone pollution and how to resolve it [here](https://angular.io/guide/change-detection-zone-pollution).
|
||||||
|
|
||||||
|
The following video will explain more in-depth the issue of this application.
|
||||||
|
|
||||||
<video controls src="https://user-images.githubusercontent.com/30832608/209819211-58d9ddcf-e1ad-4a78-8a7a-2be9d729e3f1.mov">
|
<video controls src="https://user-images.githubusercontent.com/30832608/209819211-58d9ddcf-e1ad-4a78-8a7a-2be9d729e3f1.mov">
|
||||||
</video>
|
</video>
|
||||||
|
|
||||||
## Statement
|
## Statement
|
||||||
|
|
||||||
Your goal for this challenge is to avoid all unnecessary change detection cycles and trigger a CD only when needed.
|
Your goal for this challenge is to avoid all unnecessary change detection cycles and trigger a change detection only when needed.
|
||||||
|
|
||||||
## Constraint:
|
## Constraint:
|
||||||
|
|
||||||
You cannot opt-out of zone.js. If this code is part of a large project and you opt out of zone.js, you will break many things within your application.
|
You cannot opt-out of Zone.js globally. If this code is part of a large project and you opt out of Zone.js, you will break your application without any doubt.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -5,33 +5,37 @@ sidebar:
|
|||||||
order: 34
|
order: 34
|
||||||
---
|
---
|
||||||
|
|
||||||
:::note
|
|
||||||
WIP: The following documentation will be reviewed and improved. However, you can still take on the challenge. If you don't understand a certain part, please feel free to reach out or create an issue.
|
|
||||||
:::
|
|
||||||
|
|
||||||
<div class="chip">Challenge #34</div>
|
<div class="chip">Challenge #34</div>
|
||||||
|
|
||||||
## Information
|
## Information
|
||||||
|
|
||||||
In this series of challenges, you will learn how to optimize and enhance the performance of your Angular Application.
|
In this challenge, we will explore the differences and impacts of using `ChangeDetectionStrategy.Default` versus `ChangeDetectionStrategy.OnPush`.
|
||||||
|
|
||||||
The first step is to download the [Angular DevTools Chrome extention](https://chrome.google.com/webstore/detail/angular-devtools/ienfalfjdbdpebioblfackkekamfmbnh) if you haven't already done so. This extension allows you to profile your application and detect performance issues.
|
You can read the [Angular documentation](https://angular.io/guide/change-detection-skipping-subtrees) to learn more about the differences between these strategies.
|
||||||
|
|
||||||
In this challenge, we will explore the differences and impacts of using `ChangeDetectionStrategy.Default` versus `ChangeDetectionStrategy.OnPush`. To provide a clearer demonstration, I have added color enlightment to each component and each row in our application. However, in real-world scenarios, you will not have such visualization. This is where the Angular DevTool profiler comes to the rescue.
|
In this challenge, all components start with the `Default` strategy. When you type letters inside the input field, you will notice that all components are highlighted in orange.
|
||||||
|
|
||||||
Start by serving this application by running: `npx nx serve performance-default-onpush` inside your terminal. Then open Chrome DevTool by pressing **F12** and switch to the Angular Tab. From there you can select the Profiler tab as shown below.
|
:::note
|
||||||
|
I added color highlighting to each component and each row to provide a better visualization of when a component is rerendered.
|
||||||
|
:::
|
||||||
|
|
||||||

|
As you can see, each letter triggers a new change detection cycle, and all components are rerendered, causing performance issues.
|
||||||
|
|
||||||
Start profiling your application and type some letters inside the input field. You will notice that each element of your application will flash at each change detection cycle and the profiler will show you a bar for each change detection cycle.
|
Let's use the <b>Angular DevTool</b> to profile our application and understand how this tool can help us understand what is happening inside our application.
|
||||||
|
|
||||||
If you click on one of the bars (indicated by the yellow arrow on the picture below), you can see that `PersonListComponent`, `RandomComponent` and all the `MatListItem` are impacted by the change detection cycle, even when we only interact with the input field.
|
:::note
|
||||||
|
If you don't know how to use it, read [the performance introduction page](/challenges/angular-performance/) first and come back after.
|
||||||
|
:::
|
||||||
|
|
||||||

|
Now, start profiling your application and type some letters inside the input field to trigger some change detection cycles.
|
||||||
|
|
||||||
|
If you click on one of the bars (indicated by the yellow arrow in the picture below), you can see that `PersonListComponent`, `RandomComponent`, and all the `MatListItem` are impacted by the change detection cycle, even when we only interact with the input field.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Statement
|
## Statement
|
||||||
|
|
||||||
The goal of this challenge is to improve the clustering of change detection within the application.
|
The goal of this challenge is to improve the clustering of change detection within the application using the `OnPush` change detection strategy, but not only...
|
||||||
|
|
||||||
## Hints:
|
## Hints:
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
---
|
||||||
|
title: 🟢 Memoization
|
||||||
|
description: Challenge 35 is about learning
|
||||||
|
sidebar:
|
||||||
|
order: 35
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class="chip">Challenge #35</div>
|
||||||
|
|
||||||
|
## Information
|
||||||
|
|
||||||
|
In Angular, <b>pure Pipes</b> are very powerful because the value is memoized, which means if the input value doesn't change, the `transform` function of the pipe is not recomputed, and the cached value is outputted.
|
||||||
|
|
||||||
|
You can learn more about pipes in the [Angular documentation](https://angular.io/guide/pipes) and inside this [deep dive article](https://medium.com/ngconf/deep-dive-into-angular-pipes-c040588cd15d).
|
||||||
|
|
||||||
|
In this challenge, we start with a button to load a list of people. Each person is associated with a number, and we will use the Fibonacci calculation to create a heavy computation that will slow down the application.
|
||||||
|
|
||||||
|
Once the list is loaded, try typing some letters inside the input field. You will notice that the application is very slow, even though you are only performing very basic typing.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
We will not focus on the initial loading of the list in this challenge.
|
||||||
|
:::
|
||||||
|
|
||||||
|
Let's use the <b>Angular DevTool</b> to profile our application and understand how this tool can help us understand what is happening inside our application.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
If you don't know how to use it, read [the performance introduction page](/challenges/angular-performance/) first and come back after.
|
||||||
|
:::
|
||||||
|
|
||||||
|
Now, start profiling your application and type some letters inside the input field. You will see some red bars showing up inside the profiler panel.
|
||||||
|
|
||||||
|
If you click on one of the bars (indicated by the yellow arrow in the picture below), you will see that the change detection cycle is taking more than 3s in `PersonListComponent`.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Statement
|
||||||
|
|
||||||
|
The goal of this challenge is to understand what is causing this latency and to improve it.
|
||||||
|
|
||||||
|
## Hints:
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Hint 1</summary>
|
||||||
|
|
||||||
|
Use `Pipes` to memoize the Fibonnaci computation.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Start the project by running: `npx nx serve performance-memoized`.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::tip[Reminder]
|
||||||
|
Your PR title must start with <b>Answer:35</b>.
|
||||||
|
:::
|
||||||
|
|
||||||
|
<div class="article-footer">
|
||||||
|
<a
|
||||||
|
href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A35+label%3Aanswer"
|
||||||
|
alt="Memoization community solutions">
|
||||||
|
❖ Community Answers
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A35+label%3A"answer+author"'
|
||||||
|
alt="Memoization solution author">
|
||||||
|
▶︎ Author Answer
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
title: Angular Performance
|
||||||
|
prev: false
|
||||||
|
next: false
|
||||||
|
description: Challenge 34 is about learning the difference between Default and OnPush Change Detection Strategy.
|
||||||
|
sidebar:
|
||||||
|
order: 1
|
||||||
|
---
|
||||||
|
|
||||||
|
import { LinkCard } from '@astrojs/starlight/components';
|
||||||
|
|
||||||
|
In this series of challenges about performance, you will learn how to optimize and enhance the performance of your Angular application.
|
||||||
|
|
||||||
|
Before starting to resolve any challenge, I invite you to download the [Angular DevTools Chrome extention](https://chrome.google.com/webstore/detail/angular-devtools/ienfalfjdbdpebioblfackkekamfmbnh) if you haven't already done so.
|
||||||
|
|
||||||
|
This extension allows you to profile your application and detect performance issues, which is very useful for understanding where performance issues can occur.
|
||||||
|
|
||||||
|
## How to use it
|
||||||
|
|
||||||
|
When you serve an Angular application, you can inspect a page by pressing <b>F12</b>, which will open the <b>Chrome developer tools</b>. Then navigate to the <b>Angular tab</b>. From there, you can select the <b>Profiler tab</b> as shown below.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
You can now profile your application by clicking on the record button. You can play with your application and see when change detection is triggered and which components are rerendered.
|
||||||
|
|
||||||
|
:::tip[Learn more]
|
||||||
|
You can learn more on the [documentation page](https://angular.io/guide/devtools).
|
||||||
|
:::
|
||||||
|
|
||||||
|
Now that you know how to use the <b>Angular DevTool</b>, you can choose a challenge, profile it, and resolve it.
|
||||||
|
|
||||||
|
<LinkCard
|
||||||
|
title="🟠 Optimize Change Detection"
|
||||||
|
description="Learn how to remove zone pollution."
|
||||||
|
href="/challenges/angular-performance/12-scroll-cd/"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<LinkCard
|
||||||
|
title="🟢 Default vs OnPush"
|
||||||
|
description="Learn the difference between Default and OnPush change detection strategies."
|
||||||
|
href="/challenges/angular-performance/34-default-onpush/"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<LinkCard
|
||||||
|
title="🟢 Memoization"
|
||||||
|
description="Learn the power of pure pipes."
|
||||||
|
href="/challenges/angular-performance/35-memoize/"
|
||||||
|
/>
|
||||||
@@ -11,11 +11,13 @@ WIP: The following documentation will be reviewed and improved. However, you can
|
|||||||
|
|
||||||
<div class="chip">Challenge #32</div>
|
<div class="chip">Challenge #32</div>
|
||||||
|
|
||||||
|
:::note
|
||||||
This challenge is inspired by a real-life example that I simplified to create this nice challenge.
|
This challenge is inspired by a real-life example that I simplified to create this nice challenge.
|
||||||
|
:::
|
||||||
|
|
||||||
## Information
|
## Information
|
||||||
|
|
||||||
In this small application, we have a navigation menu to route our application to either `barComponent` or `FooComponent`. However our application is not loading and no errors are displayed inside the console.
|
In this small application, we have a navigation menu to route our application to either `BarComponent` or `FooComponent`. However our application is not loading and no errors are displayed inside the console.
|
||||||
|
|
||||||
## Statement
|
## Statement
|
||||||
|
|
||||||
@@ -94,6 +94,10 @@ b {
|
|||||||
color: var(--sl-color-accent-high);
|
color: var(--sl-color-accent-high);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.starlight-aside--tip b {
|
||||||
|
color: var(--sl-color-asides-text-accent);
|
||||||
|
}
|
||||||
|
|
||||||
.main-page-footer {
|
.main-page-footer {
|
||||||
margin-top: 2rem !important;
|
margin-top: 2rem !important;
|
||||||
font-size: var(--sl-text-sm);
|
font-size: var(--sl-text-sm);
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
<!-- TODO: add title of your exercice -->
|
|
||||||
<h1>{Title of your exercice}</h1>
|
|
||||||
|
|
||||||
<!-- TODO: Add your name -->
|
|
||||||
|
|
||||||
> Author: {Your name}
|
|
||||||
|
|
||||||
<!-- TODO: add Information/Statement/Rules/Constraint/Steps -->
|
|
||||||
|
|
||||||
## Information
|
|
||||||
|
|
||||||
## Statement
|
|
||||||
|
|
||||||
### Step 1
|
|
||||||
|
|
||||||
### Step 2
|
|
||||||
|
|
||||||
### Constraints:
|
|
||||||
|
|
||||||
### Submitting your work
|
|
||||||
|
|
||||||
<!-- To replace
|
|
||||||
{Project name} by your project name
|
|
||||||
{challenge number} by the following number (To be find inside the main readme) -->
|
|
||||||
|
|
||||||
1. Fork the project
|
|
||||||
2. clone it
|
|
||||||
3. npm ci
|
|
||||||
<!-- TODO: add you project app name directory -->
|
|
||||||
4. `npx nx serve {project app name}`
|
|
||||||
5. _...work on it_
|
|
||||||
6. Commit your work
|
|
||||||
<!-- TODO: add your challenge number -->
|
|
||||||
7. Submit a PR with a title beginning with **Answer:{challenge number}** that I will review and other dev can review.
|
|
||||||
|
|
||||||
<!-- TODO: add challenge number and project Name -->
|
|
||||||
|
|
||||||
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A{challenge number}+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="{Project name}"/></a>
|
|
||||||
|
|
||||||
<!-- TODO: uncomment when done late -->
|
|
||||||
<!-- <a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A{challenge number}+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="{Project name} solution author"/></a>
|
|
||||||
<a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="{Project name} blog article"/></a> -->
|
|
||||||
|
|
||||||
<!-- TODO: you can add your twitter or anything else if you wish -->
|
|
||||||
<!-- _You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a> -->
|
|
||||||
@@ -8,7 +8,8 @@
|
|||||||
"start": "nx serve",
|
"start": "nx serve",
|
||||||
"build": "nx build",
|
"build": "nx build",
|
||||||
"test": "nx test",
|
"test": "nx test",
|
||||||
"prepare": "husky install"
|
"prepare": "husky install",
|
||||||
|
"doc:dev": "cd docs && npm run dev"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
Reference in New Issue
Block a user