SPA Frameworks Overview (Full)

Single Page Applications (SPAs) have emerged as a modern trend, consolidating all your application functions into a single, cohesive page. In the ever-evolving landscape of SPA development, mastering the right tools and frameworks is essential.

Traditional approaches to frontend development are giving way to more efficient, dynamic, and user-friendly Single Page Application (SPA) frameworks. In this short tutorial, we'll explore three of the most prominent SPA frameworks: Angular, React, and Vue, and learn how to create some basic functionality with them.

Why to chose SPA Framworks over Traditional Frontend Development

An application developed using the traditional frontend development approach is typically built using a combination of HTML, CSS, and JavaScript, and it requires a full page load for each interaction. For example, if you click a "Submit" button, the entire application will reload to handle the user interaction. This results in a less fluid and responsive user experience. Furthermore, maintaining an application that follows traditional frontend development can be more challenging as the application grows.

What's the solution? Fortunately, there are several SPA frameworks available, including Angular, React, and Vue, that make the development process easier and load only the elements that the user is currently executing. These frameworks have gained popularity due to their exceptional efficiency, flexibility, and an array of advanced features such as state management, routing mechanisms, and reusable components.

Besides, when a server loads a traditional site, it is required to load a number of files, including HTML, CSS, JavaScript, and more, which can make the initial loading slow. Even if there are some files that are not required for the initial loading, the server still spends time loading those files. However, when using SPA frameworks, the server only loads files when it is required. This makes the application run faster than the traditional approach.

Let's take a quick overview of the most popular SPA frameworks: Angular, React, and Vue. We will also examine the limitations of these SPA frameworks to assist you in making comparisons among them.

Angular: Empowering Large and Complex Applications

Angular, a robust SPA framework, has emerged as a powerhouse for building large and complex web applications. It offers a comprehensive set of tools, such as routing, form handling, and dependency injection, that streamline development.

Key featuresDrawbacks
Angular contains a comprehensive set of tools and functionalities like routing, form handling, dependency injection, and many more.Requires a significant amount of code.
It offers two-way data binding, making your application dynamic and loading the changes immediately.Performance overhead may occur due to large bundle size.
It enables you to create reusable and maintainable components.Limited flexibility and customization in some cases.
Angular provides better tooling supportRequire extra support for SEO optimization.

React: Crafting Modern UIs

React, a go-to choice for creating modern web applications, focuses on crafting responsive and dynamic user interfaces. Its component-based architecture promotes code reusability and maintainability.

Key featuresDrawbacks
React contains Component-based architecture, enabling you to create reusable components for your application.Limited to the view layer. It's the part of an application with which users can interact, such as buttons, links, images, etc.
It uses JSX (JavaScript XML) which allows you to write HTML-like code directly in JavaScript.Performance may vary based on application size.
React enables you to convert your SPA in a mobile application easily and quickly through it React-Native syntax.React evolves rapidly, compatibility issues may occur for new React versions.
React supports unidirectional data flow and ensures your data flows in a single direction (Parent to child).---
React offers several performance optimization techniques, such as memoization, lazy loading---

Vue: Lightweight and User-Friendly

Vue has gained popularity for its powerful and user-friendly features, making it ideal for creating highly interactive web applications. Its lightweight nature and flexibility are notable advantages.

Key featuresDrawbacks
Vue also supports Component-based architectureLimited plugins available
It offers a concise and easy-to-use syntax for handling action events like mouse clicks, drag and drop, scrolling effects, etc.Complex integration
Vue contains a watcher that enables you to track data changes in your application.Vue isn't compatible with older version browsers. (Less than Internet Explorer 11).
Vue provides excellent performance through its lightweight feature.---
High flexiblity.---

Getting Started with SPA Frameworks

Here is how you can initiate your project with different SPA frameworks. Please note that the SPA frameworks mentioned in this tutorial require Node.js and npm available in your system. So make sure you have Node.js and npm installed on your machine. Let's imagine you're creating a Weather Forecast application.

Setting up a project with Angular

If you selected Angular, first you need to install Angular CLI with the command:

npm install -g @angular/cli

After successful installation, you can now create your angular application using the command:

ng new my-weather-app

To start your project, move to your project directory and execute the command:

ng serve

You'll have the below file and folder structure after a successful project setup.

- src/
  - app/
    - app.component.ts
  - assets/
  - environments/
  - styles.css
  - index.html
- node_modules/
- angular.json
- tsconfig.json
- package.json
- tslint.json (if used)

Here is a simple "Hello World" example in Angular:

// Angular Hello World Component
import { Component } from '@angular/core';

@Component({
  selector: 'app-hello-world',
  template: '<div>Hello, World!</div>',
})
export class HelloWorldComponent {}

Setting up a project with React

If you're using React, just type the below command to create your project:

npx create-react-app my-weather-app

To start your project, move to your project directory and execute the command:

npm start

You'll have the below file and folder structure after a successful project setup.

- node_modules/
- public/
- src/
  - index.js
  - App.js
  - components/
  - assets/
- package.json
- babel.config.js (if used)
- webpack.config.js (if ejected from Create React App)

Here is a simple "Hello World" example in React:

// React Hello World Component
import React from 'react';

function HelloWorld() {
  return <div>Hello, World!</div>;
}

export default HelloWorld;

Setting up a project with Vue

In the case of Vue, you need to install the Vue CLI using the command:

npm install -g @vue/cli

Now create your project using:

vue create my-weather-app

To start your project, move to your project directory and execute the command:

npm run serve

You'll have the below file and folder structure after a successful project setup.

- node_modules/
- public/
- src/
  - main.js
  - App.vue
  - components/
  - assets/
  - router/ (if using Vue Router)
  - store/ (if using Vuex)
  - views/
- package.json
- vue.config.js (if needed)

Here is a simple "Hello World" example in Vue:

<!-- Vue.js Hello World Component -->
<template>
  <div>Hello, World! (Vue.js)</div>
</template>

Building a Form in SPA Frameworks

Forms play a critical role in any application by letting users provide information and sending it to the system. In this section, we'll build forms using different Single Page Application (SPA) frameworks.

Designing Form with React

If you plan to use React for your SPA, you can take a look at this simple form developed with React,

import React, { useState } from 'react';

function GetWhether() {
  const [inputValue, setInputValue] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    // Handle form submission here
    console.log(inputValue);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
        placeholder="Enter your location"
      />
      <button type="submit">Submit</button>
    </form>
  );
}

export default MyForm;

Let's explain the code part by part,

LinesExplanation
const [inputValue, setInputValue] = useState('');Handles user input
const handleSubmit = (e) => { e.preventDefault(); // Handle form submission here console.log(inputValue); };This is an action event on user input. Here e.preventDefault(); prevents all system default
return ( <form onSubmit={handleSubmit}> <input type="text" value={inputValue} onChange={(e) => setInputValue(e.target.value)} placeholder="Enter your location" /> <button type="submit">Submit</button> </form> );A form containing one input field and a submit button.

Designing Form with Angular

With Angular, you can design a form like the one below,

<!-- myform.component.html -->
<form (ngSubmit)="onSubmit()">
  <input type="text" [(ngModel)]="inputValue" placeholder="Enter your location" name="inputField" />
  <button type="submit">Submit</button>
</form>
// myform.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-myform',
  templateUrl: './myform.component.html',
  styleUrls: ['./myform.component.css']
})
export class SimpleFormComponent {
  inputValue: string = '';

  onSubmit() {
    // Handle form submission here
    console.log(this.inputValue);
  }
}

Let's break the code and see how it works,

LinesExplanation
@Component({ selector: 'app-myform', templateUrl: './myform.component.html', styleUrls: ['./myform.component.css'] })Initializing the resources
export class SimpleFormComponent { inputValue: string = ''; onSubmit() { // Handle form submission here console.log(this.inputValue); } }Handles the user input. Here the inputValue stores the user input and the method onSubmit() processes the user input

Designing Form with Vue

Here is a simple form designed in Vue.

<template>
  <form @submit.prevent="onSubmit">
    <input v-model="inputValue" type="text" placeholder="Enter your location" />
    <button type="submit">Submit</button>
  </form>
</template>
<script>
export default {
  data() {
    return {
      inputValue: ''
    };
  },
  methods: {
    onSubmit() {
      // Handle form submission here
      console.log(this.inputValue);
    }
  }
};
</script>

Check the explanation table to understand how the code works.

LinesExplanation
data() { return { inputValue: '' }; },Handles user input
methods: { onSubmit() { // Handle form submission here console.log(this.inputValue); } }the method onSubmit() processes the user input

Making API Calls in SPA Frameworks

API calls involve sending requests to a remote server to fetch specific data, and the server responds with the requested information. Let's explore how to make API calls in single-page application (SPA) frameworks.

Making API Calls in React

Here is a simple API call with React.

import React, { useEffect, useState } from 'react';

function App() {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch('https://api.example.com/data') // Replace with your API endpoint
      .then((response) => response.json())
      .then((data) => setData(data))
      .catch((error) => console.error('API Call Failed: ', error));
  }, []);

  return (
    <div>
      {data ? (
        <div>{JSON.stringify(data)}</div>
      ) : (
        <div>Loading...</div>
      )}
    </div>
  );
}

export default App;

Let's take a quick look at the explanation table that makes it easy to understand

LinesExplanation
const [data, setData] = useState(null);Handles user data
useEffect(() => { fetch('https://api.example.com/data') // Replace with your API endpoint .then((response) => response.json()) .then((data) => setData(data)) .catch((error) => console.error('API Call Failed: ', error)); }, []);Makes the API call using the fetch(), get the response data and process the user data
return ( <div> {data ? ( <div>{JSON.stringify(data)}</div> ) : ( <div>Loading...</div> )} </div> );Shows the result of API call

Making API Calls in Angular

If you're using Angular, you can make the API call like the one below,

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
export class AppComponent implements OnInit {
  data: any;

  constructor(private http: HttpClient) {}

  ngOnInit() {
    this.http.get('https://api.example.com/data') // Replace with your API endpoint
      .subscribe((response) => {
        this.data = response;
      }, (error) => {
        console.error('API call failed: ', error);
      });
  }
}

Let's check the explanation table for more details,

FunctionExplanation
@Component({ selector: 'app-root', templateUrl: './app.component.html', })Initializing Resources
data: any;Variable that holds user data
ngOnInit() { this.http.get('https://api.example.com/data') // Replace with your API endpoint .subscribe((response) => { this.data = response; }, (error) => { console.error('API call failed: ', error); }); }Makes the HTTP requst using this.http.get() and process the response data.

Making API Calls in Vue

Using Vue, making an API call is much simpler,

<template>
  <div>
    {{ data ? JSON.stringify(data) : 'Loading...' }}
  </div>
</template>
<script>
import axios from 'axios';

export default {
  data() {
    return {
      data: null,
    };
  },
  mounted() {
    axios.get('https://api.example.com/data') // Replace with your API endpoint
      .then((response) => {
        this.data = response.data;
      })
      .catch((error) => {
        console.error('API call failed: ', error);
      });
  },
};
</script>

Let's take a quick look at the explanation table that makes it easy to understand

FunctionExplanation
data() { return { data: null, }; },Handles the data
mounted() { axios.get('https://api.example.com/data') // Replace with your API endpoint .then((response) => { this.data = response.data; }) .catch((error) => { console.error('API call failed: ', error); }); },Makes the HTTP requset using axios.get() and process the response data.

Displaying Data in SPA Frameworks

Showing data is a common task in any Single Page Application (SPA). In this section, we'll explore how to display data using React, Angular, and Vue.

Displaying Data in React

Here is how you can display our results in React.

import React from 'react';

function App() {
  const data = ["Item 1", "Item 2", "Item 3"];

  return (
    <div>
      <h1>Items:</h1>
      <ul>
        {data.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>
    </div>
  );
}

export default App;

Let's take a quick look at the explanation table,

FunctionExplanation
const data = ["Item 1", "Item 2", "Item 3"];Your data
{data.map((item, index) => ( <li key={index}>{item}</li> ))}Mapping the data and making it visible using <li></li>

Displaying Data in Angular

Here is a simple data visualization in Angular

<!-- app.component.html -->
<div>
  <h1>Items:</h1>
  <ul>
    <li *ngFor="let item of data">{{ item }}</li>
  </ul>
</div>
// app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
export class AppComponent {
  data = ["Item 1", "Item 2", "Item 3"];
}

This is how the code works,

FunctionExplanation
<li *ngFor="let item of data">{{ item }}</li>Visualizing the data in <li></li> tag
@Component({ selector: 'app-root', templateUrl: './app.component.html', })Initializing the components
data = ["Item 1", "Item 2", "Item 3"];Data to visualize

Displaying Data in Vue

This is how you can visualize data in Vue,

<template>
  <div>
    <h1>Items:</h1>
    <ul>
      <li v-for="(item, index) in data" :key="index">{{ item }}</li>
    </ul>
  </div>
</template>
<script>
export default {
  data() {
    return {
      data: ["Item 1", "Item 2", "Item 3"],
    };
  },
};
</script>

Let's take a close view of the code,

FunctionExplanation
<li v-for="(item, index) in data" :key="index">{{ item }}</li>Visualizing the data in <li></li> tag
data() { return { data: ["Item 1", "Item 2", "Item 3"], }; }, };Handles the data

State Management in SPAs

A 'state' is data that an application keeps to manage its behavior and user interaction. For instance, when you enter something in an input field, you alter the state of that field from empty to having a value.

Let's delve into how SPA frameworks handle these state changes:

State Management in React

Here is how React manages states,

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}

export default Counter;

Let's see how the code works,

FunctionExplanation
const [count, setCount] = useState(0);Handles the user state
const increment = () => { setCount(count + 1); };Here the method increment() take action during any state change
return ( <div> <p>Count: {count}</p> <button onClick={increment}>Increment</button> </div> );Showing the output after state change

State Management in Angular

Here is an example of state management in Angular.

<!-- counter.component.html -->
<div>
  <p>Count: {{ count }}</p>
  <button (click)="increment()">Increment</button>
</div>
// counter.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-counter',
  templateUrl: './counter.component.html',
})
export class CounterComponent {
  count: number = 0;

  increment() {
    this.count++;
  }
}

Let's take a quick look at the explanation table that makes it easy to understand,

FunctionExplanation
<div> <p>Count: {{ count }}</p> <button (click)="increment()">Increment</button> </div>Shows the output after state change
@Component({ selector: 'app-counter', templateUrl: './counter.component.html', })Initializing resources
export class CounterComponent { count: number = 0; increment() { this.count++; } }Main class contain a method ncrement() handles the state change. In this case, it increments the value when a user clicks the Increment button

State Management in Vue

If you're using Vue, you can manage the states like the below,

<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>
<script>
export default {
  data() {
    return {
      count: 0,
    };
  },
  methods: {
    increment() {
      this.count++;
    },
  },
};
</script>

Let's zoom in the code,

FunctionExplanation
<template> <div> <p>Count: {{ count }}</p> <button @click="increment">Increment</button> </div> </template>A HTML template containing necessary components
data() { return { count: 0, }; },Handles the state data
methods: { increment() { this.count++; }, }, };the method increment() handles the state change. In this case, it increments the value when a user clicks the Increment button

Styling and Layout

Now that you can design a form for your application, control the state, make API calls to get the necessary data, and display it to your users, there's one aspect we haven't addressed: the visual appeal.

Let's optimize the UI to make it more attractive.

By utilizing CSS, or Cascading Style Sheets, you can easily enhance the friendliness and visual appeal of your application's user interface. It is a stylesheet language that enables you to define the visual presentation of your web application. There are three ways to apply CSS in your application:

Inline CSS In this way, you need not use any separate CSS file for styling. You can define the CSS inside the HTML element using the "style" attribute.

<p style="color:red">Your text here</p>

Internal CSS This method allows you to style your HTML elements inside your HTML file using the <style> tag.

<style>
  p {
    color: red;
  }
</style>
<p>Your text here</p>

External CSS You need to create a separate CSS file to define all your styles for your application. The advantage of using this method is that you can share the CSS file across all your application files. So you need not to define the same styling again and again.

Styling with External CSS libraries

External CSS libraries consist of pre-defined CSS styles that you can readily apply to your application without the need to create styles from scratch. For instance, Bootstrap is a well-known CSS library that enables you to achieve perfect alignment, responsiveness, and an attractive appearance for your application with a simple inclusion using a <link> tag.

Here are a few steps that you can take to include external CSS libraries in your application

Step 1: Find an External CSS library First, you need to choose a CSS library that suits your project's needs. Popular CSS libraries include Bootstrap, Foundation, Bulma, Materialize, and many others. These libraries provide pre-designed styles and layout components that you can easily incorporate into your project.

Step 2: Import the library using CDN CDN allows you to import a library using a link without downloading the library. As for Bootstrap, you can include it in your project like the below,

<!-- Link to Bootstrap CSS via a CDN -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">

Now you can apply the styles directly to your application like the below,

<button class="btn btn-primary">Click me</button>

You'll get all the predefined styles in the documentation or official website of the library you selected.

Tips and best practices for responsive design

In the end, let's take a quick look at some tips and best practices that make your application UI look great and well organized in any screen size,

Make it Mobile First To make your application perfectly aligned in any screen size, start designing for mobile devices first and then progressively enhance the design for larger screens. This approach ensures a solid foundation for smaller screens and helps prioritize content and performance.

Don't make the Layout fixed When defining properties like the width and height of any elements, use relative units like percentages instead of using fixed width. This will allow the element to adapt to different screen sizes.

Use Media Queries CSS contains media queries that allow you to set styles for different screen sizes. Carefully define the breakpoints where your UI needs adjustments such as changing the number of columns, and font sizes or hiding/showing certain elements.

@media (max-width: 768px) {
  /* Styles for screens up to 768px wide */
}
@media (min-width: 769px) {
  /* Styles for screens 769px wide and larger */
}

Use Relative Font Sizing When sizing font, Use relative units like em or rem. This will allow you to scale the texts appropriately on different devices, making the text more readable on both small and large screens.

Create Mobile-Friendly Navigation For creating a navigation menu, always make it mobile-friendly to save space on small devices. Also, make sure navigation items are easily accessible and usable on touch screens.