contents
Published on 2025-04-17
In today's fast-paced digital world, website performance is crucial for delivering a seamless user experience. Slow API response times can significantly hinder user satisfaction and search engine rankings. This blog post will guide you through optimizing web performance by reducing API response time using Next.js and Django REST Framework. We'll also explore how to leverage WebOpt for SEO, UI, and responsive testing to ensure your web application is top-notch.
API response time plays a critical role in the overall performance of a web application. Whether you're fetching data for rendering a page or processing user inputs, slow APIs can create bottlenecks that affect both front-end and back-end performance.
The combination of Next.js and Django REST Framework is a powerful duo for building scalable and efficient applications. Next.js offers server-side rendering (SSR), static site generation (SSG), and dynamic routing, while Django REST Framework provides a robust backend for managing data and handling API requests.
# Install Django and Django REST Framework
pip install django djangorestframework
# Create a new Django project
django-admin startproject myproject
for example(django-admin startproject blog)
# Navigate into the project directory
cd myproject
# Create a new app
python manage.py startapp myapp
for example (python manage.py startapp optimize)
Let’s define a simple model in optimize/models.py:
from django.db import models
class EmployeeInfo(models.Model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
age = models.IntegerField()
email = models.EmailField(max_length=1000)
country = models.CharField(max_length=1000)
city = models.CharField(max_length=1000)
gender = models.CharField(max_length=100)
def __str__(self):
return self.first_name
class EmployeeSalary(models.Model):
employee_id = models.ForeignKey(EmployeeInfo, related_name="emp", on_delete=models.CASCADE)
salary = models.IntegerField()
skill = models.CharField(max_length=500)
Next, create serializers for the models in optimize/serializers.py:
from rest_framework import serializers
from .models import EmployeeInfo, EmployeeSalary
class EmployeeInfoSerializer(serializers.ModelSerializer):
class Meta:
model = EmployeeInfo
fields = "__all__"
class EmployeeSalarySerializer(serializers.ModelSerializer):
employee_id = EmployeeInfoSerializer()
class Meta:
model = EmployeeSalary
fields = "__all__"
class EmployeeDetailSerializer(serializers.ModelSerializer):
info = serializers.SerializerMethodField()
class Meta:
model = EmployeeInfo
fields = ["id","first_name", "last_name", "age", "email", "country", "city", "gender", "info"]
def get_info(self, obj):
composer_credit = list(EmployeeSalary.objects.filter(id=obj.id).values())
usercredential = {}
if len(composer_credit):
usercredential["salary"] = composer_credit[0]["salary"]
usercredential["skill"] = composer_credit[0]["skill"]
return usercredential
In optimize/views.py, we’ll create API views that handle requests efficiently.
from rest_framework import generics
from .models import EmployeeInfo, EmployeeSalary
from .serializer import EmployeeInfoSerializer
class EmployeeListView(generics.RetrieveAPIView):
queryset = EmployeeInfo.objects.prefetch_related('emp').all()
serializer_class = EmployeeInfoSerializer
lookup_field='employee_id'
class EmployeeFullInfoView(generics.RetrieveAPIView):
queryset = EmployeeInfo.objects.prefetch_related('emp').all()
serializer_class = EmployeeInfoSerializer
class EmployeeDetailsView(viewsets.ModelViewSet):
queryset = EmployeeInfo.objects.all()
serializer_class = EmployeeDetailSerializer
Now, map these views to URLs in myapp/urls.py:
from django import views
from django.urls import path
from .views import EmployeeFullInfoView,EmployeeDetailsView
employee = EmployeeDetailsView.as_view({'get':'list'})
urlpatterns = [
path("employee/<int:pk>", EmployeeFullInfoView.as_view(), name="employee"),
path("employee-details/", employee),
]
Include these URLs in your main urls.py file:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('optimize/', include('optimize.urls')),
]
Finally, apply the migrations and start the server:
python manage.py makemigrations
python manage.py migrate
python manage.py runserver
Ensure that you have Node.js and npm installed on your machine.
node -v
npm -v
Use the following command to create a new Next.js project.
npx create-next-app@latest my-next-app
cd my-next-app
Start the development server to ensure everything is working.
npm run dev
Navigate to http://localhost:3000 in your browser to see your new Next.js application.
Create a Utility Folder: Inside your src or lib directory, create a Compoenents folder to hold your API request functions.
Create API Functions: Inside the Components folder, create a file named Fetch.js and define functions to fetch data from the Django REST API.
const API_BASE_URL = 'http://localhost:8000';
export async function EmployeeGetApi(event, method, api) {
var response_data;
await fetch(`${API_BASE_URL}` + api, {
method: method,
headers: {
'Content-Type': 'application/json',
},
}).then((res) => {
console.log(res);
return res.json()
}).then(data => {
response_data = data
})
.catch(error => {
response_data = error
});
return response_data
}
In pages/index.js, add the following code.
import Image from "next/image";
import { product_info } from "@/components/Api";
import { useState, useEffect } from "react";
import { EmployeeGetApi } from "@/components/fetch";
import { useRouter } from "next/router";
export default function Home() {
const router = useRouter()
const [jsonData, setJsonData] = useState([])
async function PmcGetFunction() {
const response = await EmployeeGetApi('', "GET", "/optimize/employee-details/")
setJsonData(response)
}
useEffect(() => { PmcGetFunction() }, [])
return (
<main
className={`flex min-h-screen flex-col items-center justify-between p-24 bg-white `}
>
<div className="px-4 sm:px-6 lg:px-8">
<div className="sm:flex sm:items-center">
<div className="sm:flex-auto">
<h1 className="text-base font-semibold leading-6 text-gray-900">Users</h1>
<p className="mt-2 text-sm text-gray-700">
A list of all the users in your account including their first_name, last_name, email, age, country, city and gender.
</p>
</div>
</div>
<div className="mt-8 flow-root">
<div className="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div className="inline-block w-[700px] py-2 align-middle sm:px-6 lg:px-8">
<table className="min-w-full divide-y divide-gray-300">
<thead>
<tr>
<th scope="col" className="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-0">
Id
</th>
<th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
First_name
</th>
<th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
Last_name
</th>
<th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
Age
</th>
<th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
Email
</th>
<th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
Country
</th>
<th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
City
</th>
<th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
Gender
</th>
<th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
Salary
</th>
<th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
Skill
</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200">
{jsonData.map((person, index) => (
<tr key={index} onClick={()=>{router.push('/person/?id='+person.id)}} className="cursor-pointer">
<td className="whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-black sm:pl-0 ">
{person.id}
</td>
<td className="whitespace-nowrap px-3 py-4 text-sm text-black">{person.first_name}</td>
<td className="whitespace-nowrap px-3 py-4 text-sm text-black">{person.last_name}</td>
<td className="whitespace-nowrap px-3 py-4 text-sm text-black">{person.age}</td>
<td className="whitespace-nowrap px-3 py-4 text-sm text-black">{person.email}</td>
<td className="whitespace-nowrap px-3 py-4 text-sm text-black">{person.country}</td>
<td className="whitespace-nowrap px-3 py-4 text-sm text-black">{person.city}</td>
<td className="whitespace-nowrap px-3 py-4 text-sm text-black">{person.gender}</td>
<td className="whitespace-nowrap px-3 py-4 text-sm text-black">{person.info?.salary}</td>
<td className="whitespace-nowrap px-3 py-4 text-sm text-black">{person.info?.skill}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
</div>
</main>
);
}
In pages/person.js.js, add the following code.
import Image from "next/image";
import { user_info } from "@/components/Api";
import React, { useState, useEffect } from "react";
import { EmployeeGetApi } from "@/components/fetch";
import { useRouter } from "next/router";
export default function UserInfo() {
const router = useRouter()
const [userData, setUserInfoData] = useState([])
useEffect(() => {
if (router.query.id) {
UserInfoApi()
}
}, [])
async function UserInfoApi() {
const response = await EmployeeGetApi('', "GET", user_info + router.query.id)
setUserInfoData(response)
}
return (
<>
<div className="w-full min-h-screen bg-white">
<div className="w-[600px] min-h-[300px] pt-[80px] mx-auto">
<h1 className="text-2xl text-center font-bold">
User Information
</h1>
<div className='space-y-6 my-6'>
<div className='space-y-2 w-full'>
<label for='id' className='text-[#121212]'>
Id
</label>
<div>
<input id='id' name='first_name' value={userData.id}
type='text' className='w-full px-6 py-2 text-black border border-gray-500 focus:outline-0 focus:ring-0 ' />
</div>
</div>
<div className='space-y-2 w-full'>
<label for='first_name' className='text-[#121212]'>
First Name
</label>
<div>
<input id='first_name' name='first_name' type='text' value={userData.first_name}
className='w-full px-6 py-2 text-black border border-gray-500 focus:outline-0 focus:ring-0 ' />
</div>
</div>
<div className='space-y-2 w-full'>
<label for='last_name' className='text-[#121212]'>
Last Name
</label>
<div>
<input id='last_name' name='last_name'
value={userData.last_name}
type='text' className='w-full px-6 py-2 text-black border border-gray-500 focus:outline-0 focus:ring-0 ' />
</div>
</div>
<div className='space-y-2 w-full'>
<label for='Age' className='text-[#121212]'>
Age
</label>
<div>
<input id='age' name='age' type='text' value={userData.age}
className='w-full px-6 py-2 text-black border border-gray-500 focus:outline-0 focus:ring-0 ' />
</div>
</div>
<div className='space-y-2 w-full'>
<label for='Email' className='text-[#121212]'>
Email
</label>
<div>
<input id='email' name='email'
value={userData.email}
type='text' className='w-full px-6 py-2 text-black border border-gray-500 focus:outline-0 focus:ring-0 ' />
</div>
</div>
<div className='space-y-2 w-full'>
<label for='Gender' className='text-[#121212]'>
Gender
</label>
<div>
<input id='gender' name='gender' type='text' value={userData.gender}
className='w-full px-6 py-2 text-black border border-gray-500 focus:outline-0 focus:ring-0 ' />
</div>
</div>
<div className='space-y-2 w-full'>
<label for='Country' className='text-[#121212]'>
Country
</label>
<div>
<input id='country' name='country' type='text' value={userData.country}
className='w-full px-6 py-2 text-black border border-gray-500 focus:outline-0 focus:ring-0 ' />
</div>
</div>
<div className='space-y-2 w-full'>
<label for='City' className='text-[#121212]'>
City
</label>
<div>
<input id='city' name='city' type='text' value={userData.city}
className='w-full px-6 py-2 text-black border border-gray-500 focus:outline-0 focus:ring-0 ' />
</div>
</div>
</div>
<div>
</div>
</div>
</div>
</>
)
}
npm run dev
Integrate WebOpt: Utilize the WebOpt UI testing tool to continuously monitor your application. WebOpt offers powerful network analysis capabilities that allow you to capture and analyze network traffic during user interactions, such as mousedown events. This feature helps identify performance bottlenecks, monitor response times, and optimize resource loading.
Network Traffic Analysis: With WebOpt, you can capture and analyze network requests made by your application. This is especially useful for detecting slow API responses, large assets, or unoptimized third-party scripts.
Response Time Calculation: WebOpt provides detailed response time metrics, enabling you to identify and address performance issues that could affect your users' experience.
Cross-Browser Compatibility: Alongside network analysis, WebOpt also ensures your application performs consistently across different browsers and devices.
Optimize for Performance: Leverage the insights from WebOpt's network analysis to optimize your application's performance. By reducing unnecessary network requests and improving response times, you can enhance the overall user experience and ensure your application runs smoothly under various conditions.
In conclusion, WebOpt serves as a robust tool for continuously monitoring and optimizing your application's performance. By integrating WebOpt, you gain access to advanced network traffic analysis and response time metrics, allowing you to identify and resolve performance bottlenecks effectively. Additionally, WebOpt's cross-browser compatibility testing ensures a consistent user experience across different platforms. Utilizing these insights, you can make data-driven optimizations, reduce unnecessary network requests, and improve resource loading, resulting in a faster, smoother application experience for your users.