React versus Angular in 2024
Table of Contents
- Premise
- Step for React
- Step for Angular
- What is React?
- What is Angular?
- Developer Experience Comparison
- Performance Comparison
- Conclusion
- Resources
Premise
I set out to build a similarly styled and similarly functional todo/task list application using both React and Angular to compare their setup, developer experience, performance and general usability in 2024.
Both applications are deployed and hosted here:
Angular Task App
React Task App
Setup for React
The React application was scaffolded using bun
with Vite and following the
wizard steps, choosing React and Typescript
bun create vite react-task-list
✔ Select a framework: › React
✔ Select a variant: › TypeScript
Scaffolding project in /path/to/react-task-list...
The following packages and libraries were added to help with styling and user feedback. Tailwind for styling, Akar icons for UI icons and uuid to handle task list item unique id
"dependencies": {
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-toast": "^1.1.5",
"akar-icons": "^1.9.31",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
"lucide-react": "^0.368.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"tailwind-merge": "^2.2.2",
"tailwindcss-animate": "^1.0.7",
"uuid": "^9.0.1"
}
Setup for Angular
The Angular application was scaffolded using node
with the Angular CLI and
following the wizard steps
npx -p @angular/cli ng new angular-task-list
? Which stylesheet format would you like to use? CSS
? Do you want to enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering)? No
The following packages and libraries were added to help with styling and user feedback. Tailwind for styling, Akar icons svgs copied for the UI icons and uuid to handle task list item unique id
"dependencies": {
"@angular/animations": "^17.3.0",
"@angular/common": "^17.3.0",
"@angular/compiler": "^17.3.0",
"@angular/core": "^17.3.0",
"@angular/forms": "^17.3.0",
"@angular/platform-browser": "^17.3.0",
"@angular/platform-browser-dynamic": "^17.3.0",
"@angular/router": "^17.3.0",
"ngx-sonner": "^1.0.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"uuid": "^9.0.1",
"zone.js": "~0.14.3"
}
What is React?
React is an open-source Javascript library managed by Facebook's React team (React). It has a component-based architecture and declarative views to create interactive and complex UIs. The main advantages of using React include its reusable and predictable code, faster development time, easier debugging and enhanced developer productivity.
React uses a virtual DOM for fast rendering, employs one-way data binding with unidirectional data flow and has a smaller learning curve thus ideal for quick development. It comes with no batteries included and third-party libraries are needed to accomplish more complex logic but due to its popularity there is a huge ecosystem of libraries available.
Below is an example of the TaskCard.tsx
component from the task list
application to show the colocation of concerns, incorporating the view and logic
in the same .tsx
file.
TaskCard.tsx
import { Task } from "@/types/task";
import { Button } from "./ui/button";
import { Circle, CircleCheckFill, Cross } from "akar-icons";
const TaskCard = ({
task,
onUpdateTask,
onDeleteTask,
}: {
task: Task;
onUpdateTask: (taskId: string) => void;
onDeleteTask: (taskId: string) => void;
}) => {
return (
<div className="flex items-center p-2 justify-between bg-[#121217] rounded-xl my-1">
<div className="flex items-center">
<Button
className="bg-transparent hover:bg-transparent gap-2"
onClick={() => onUpdateTask(task.id)}
tabIndex={0}
aria-label="Check/Uncheck Task"
>
{task.completed ? (
<CircleCheckFill
className="text-cyan-300 outline-cyan-500"
strokeWidth={2}
size={20}
/>
) : (
<Circle
className="text-cyan-300 outline-cyan-500"
strokeWidth={2}
size={20}
/>
)}
<span
className={`${
task.completed
? "text-xs md:text-lg text-gray-100 font-light px-1 line-through opacity-40"
: "text-xs md:text-lg text-gray-100 font-light px-1"
}`}
>
{task.item}
</span>
</Button>
</div>
<div>
<Button
className="flex gap-2 bg-transparent text-red-500 h-8 md:h-10 hover:bg-red-800/20"
variant="destructive"
onClick={() => onDeleteTask(task.id)}
aria-label="Delete Task"
tabIndex={0}
>
<Cross strokeWidth={2} size={16} className="md:size-4 size-3" />
</Button>
</div>
</div>
);
};
export default TaskCard;
React is not very opinionated and allows you to develop the application how you see fit. This can be somewhat of a drawback of React and there are no solid conventions and how things should be done. Other drawbacks include that it's not a complete framework but simply a library and other third-party libraries may be needed for large-scale applications.
What is Angular?
Angular is a full development platform and application-design framework built on Typescript with a similar component-based architecture built and maintained by Google (Angular). It is very much a batteries included framework with integrated libraries, dependency injection and its own Angular CLI.
Angular has a strong emphasis on encapsulation and opinionated application structure. It is an object-orientated framework with an emphasis on classes. It has built-in features like RxJS, the Angular CLI and testing as well as built-in support for HTTP, Ajax and Observables. It utilizes two-way data binding, optimizes coding practices and is focused on mid-level to enterprise scale applications.
Below is an example of the app-task-card
components from the task list
application to show the separation of concerns, moving the markup and logic to
individual files.
task-card.component.html
<div class="flex items-center p-2 justify-between bg-[#121217] rounded-xl my-1">
<div class="flex items-center justify-center px-4">
<button
class="bg-transparent hover:bg-transparent gap-2 inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
(click)="updateTaskEvent(task().id)"
tabindex="0"
aria-label="Check/Uncheck Task"
>
@if (!task().completed) {
<i class="ai-circle text-[#FD33C5] text-xl"></i
><span class="text-xs md:text-lg text-gray-100 font-light px-1"
>{{ task().item }}</span
>
} @else {
<i class="ai-circle-check-fill text-[#FD33C5] text-xl"></i
><span
class="text-xs md:text-lg text-gray-100 font-light px-1"
[ngClass]="task().completed ? 'line-through opacity-40' : ''"
>{{ task().item }}</span
>
}
</button>
</div>
<div>
<button
class="h-8 px-4 flex gap-2 bg-transparent text-red-500 md:h-10 hover:bg-red-800/20 items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
(click)="deleteTaskEvent(task().id)"
aria-label="Delete Task"
tabindex="0"
>
<i class="ai-cross text-base"></i>
</button>
</div>
</div>
task-card.component.ts
import { CommonModule } from "@angular/common";
import { Component, input, output } from "@angular/core";
import { Task } from "../../../types/task";
@Component({
selector: "app-task-card",
templateUrl: "./task-card.component.html",
styleUrls: ["./task-card.component.css"],
standalone: true,
imports: [CommonModule],
})
export class TaskCardComponent {
public task = input.required<Task>();
public taskUpdateEvent = output<string>();
public taskDeleteEvent = output<string>();
public updateTaskEvent(taskId: string): void {
this.taskUpdateEvent.emit(taskId);
}
public deleteTaskEvent(taskId: string): void {
this.taskDeleteEvent.emit(taskId);
}
}
Developer Experience Comparison
React
A huge advantage to React in terms of dev experience is its popularity, meaning there are lots of resources, guides, tutorials and Stack Overflow articles out there. It is also very easy to get started with, anyone with an understanding of HTML and Javascript will feel comfortable using React, although somewhat unconventional in mixing the two in a JSX or TSX file. Another win for React is its flexibility, it isn't opinionated on how developers should treat/write the code.
Angular
A massive selling point for Angular is that it is a "batteries included" framework meaning less of a need for third-party libraries. It is focused on mid-level to
enterprise-scale apps. It promotes separation of concerns by isolating the
view from the business logic in its component.ts
and component.html
structure. It is also opinionated on how the code should be structured, this can
be an advantage for those used to an OOP style of programming paradigm but from
another perspective can be a steeper learning curve for new developers.
Performance Comparison
Both React and Angular projects are deployed to my VPS and built as a single page application with the bundle being hosted via a Docker container and Nginx web server.
Firstly let's take a look at the bundle size between the two projects, the React
project /dist
folder which was output using tsc && vite build
command. And the Angular project /dist
folder which was output using ng build
.
Output Comparison
Framework/Library | dist folder size |
---|---|
Angular | 381 KB |
React | 578 KB |
We can see that Angular is a smaller output bundle compared to React bundle.
pingdom.com Comparison
Now let's take a look at some metrics when using a website performance benchmark website such as tools.pingdom.com.
Framework/Library | Peformance Grade | Page Size | Load time | No of Requests |
---|---|---|---|---|
Angular | A - 92 | 129.8 KB | 1.91s | 10 |
React | A - 95 | 136.1 KB | 1.22s | 10 |
Here we find that although Angular is delivering a smaller page size it still loses out to React in both performance grade and load time.
pagespeed.web.dev Comparison
Next let's use pagespeed.web.dev specifically the performance metrics.
Framework/Library | Peformance Grade | First Contentful Paint | Total Blocking Time | Speed Index | Largest Contentful Paint |
---|---|---|---|---|---|
Angular | 85 | 0.6s | 30ms | 0.8s | 0.7s |
React | 94 | 0.7s | 0ms | 0.7s | 0.7s |
Again here we see that despite Angular's smaller bundle size it is marginally slower in key performance metrics such as FCP, LCP and overall speed. This must be caveated by the fact that both are small simple todo list applications and a much more complex mid to enterprise-scale application may yield much more varied results.
Conclusion
Whilst React is faster in performance metrics (i.e. on paper) and I personally prefer to develop in React's less opinionated and flexible way of functional programming both are viable options for building simple single-page application in 2024 and it really comes down to personal preference.
If you're a newer developer trying to choose your first library/framework to get into web development then I would lean more towards React, however if your goal is to land a job in large tech company then there's a high likelihood they'll be using Angular and it may be more beneficial to know the key concepts and paradigms of Angular (speaking from personal experience).
But these are only the opinions of one developer and in actual fact there's no wrong choice, the important thing is being confident and understanding the fundamentals of HTML, CSS and Javascript, a framework/library will then be much easier to learn and play around with, but that's the best thing to do, try both options, try to build something interesting and enjoy the process.