How Does the Frontend Communicate with the Backend?
How to connect the frontend and the backend?
How do they communicate?
There are many different ways how to structure a web application. The frontend can take different forms, and it can be daunting to understand how to connect the two.
This article is an overview of what goes on between the backend and the frontend of a web application - how the two communicate.
Let’s start with fundamentals.
Why do the frontend and backend exist in the first place?
The backend and frontend both work together to serve a single goal. It’s pretty helpful to keep it in mind at all times. They are made, so a user can access them. In detail this interaction can look like this:
- The user points their browser to one of your website’s urls
- This makes the browser send out one or more requests to your server
- The browser waits to receive responses from your server
- Every response is used to render a part of the site
- The user waits for the browser to render the page
- The user sees a useful and usable page
- The user interacts with the page
- Causing more requests to be sent out, to get more data and display new information, and so on
It’s all about the user.
The front- and backend make this possible by causing requests to be sent and answering with responses.
Before diving deeper, we should make sure we’re talking about the same things.
To make sure that we are on the same page, here are descriptions of possible ambiguous “big words” in this article:
Server - the abstract “thing” where the browser’s requests arrive. We don’t care about that detail to much here. It’s enough to know that the backend code is running on the server as well as other services. Request for the backend arrive at the server and are eventually passed on to your backend code.
Backend - the part of your web app which is not directly visible to the user. It receives requests and prepares data which is transmitted back to the user’s browser. Backend code is built to be running on a server and it’s never running on the user’s machine.
Browser - an application running on the user’s device. It sends out HTTP requests, receives responses, processes the received data, and uses it to render a viewable page. All of communication from the user’s side goes through their browser.
When does the browser talk to the backend?
HTTP requests arrive from the browser at the backend. Those requests may contain data in the HTTP headers or request body. The intent may be to request new data or to transmit user-created data to the backend.
HTTP requests, are constructed inside the user’s browser and sent off. There’s a response for each request, carrying information in the HTTP headers and the request body. Those responses arrive back at the backend arrive back at the user’s browser.
What needs to happen, to make the browser have to send out a request? Those requests which are fired because a user clicked a link or by JS code running in the background. But there are more possible triggers:
- The user enters a URL, which makes the browser go and request it.
- The browser reads the incoming HTML, and notices that there’s a resource it needs to load, such as a JS file, an image or a CSS file. It goes ahead and requests each with a single new HTTP request. Usually this happens while loading a website. (Those requests don’t have to go to the same backend, you could load JS from another site. People like to use CDNs for that as it’s pretty fast and convenient.)
- A user clicks on a plain-ol’ link the webpage is loaded and rendered. The browser knows that they need to navigate to a new page and requests the corresponding URL.
That’s pretty much all scenarios which can make a browser fire off requests to the backend. In each case, there are HTTP requests and responses involved.
What do they send to each other?
This one can differ! But there’s a very popular way of doing things, which is used most often. It’s a good way of doing things for 99% of all frontend-backend communication scenarios.
The magic is within the HTTP request/response payloads. The backend usually responds with certain contents of the HTTP body:
- HTML-formatted responses
- other static files (CSS, JS, images, …)
- JSON-formatted data
- No body at all. Just a status code and header fields.
The frontend sends:
- Simple HTTP requests without a body
- Form data
- JSON-formatted data
Let’s look at some examples
So far so good! Let’s take those vague descriptions from above, and look at some very concrete examples. Even though you know everything you need by now, it can be hard to connect the dots to real-life examples as there can be a lot of complexity and confusion sprinkled in.
I hope that these examples will help you see how everything fits in. And understand how the backend and frontend communicate.
Scenario: Just static content
If a browser requests something like
http://example.com/style.css, this is usually handled by the web server (like Nginx) of the backend. The request is a GET for that
resource, and the backend responds with a response, containing the content of the file.
Such static files can be served by the web application (application server) itself, but usually this is considered to be in poor taste. Web servers are really quick with this task, and web apps are kinda clumsy about it.
Vanilla Django, using Django templates
The next case is about requesting dynamic content. From the browser side,
it looks the same as requesting static content - there’s a request
which is fired off to a URL like
The browser does not care which part of the backend will handle the request, it just wants answers. (NOW.)
The requests arrives at the server, is passed to the web server (Nginx for example), and the web server hands the request over to the app server (Django handled by Gunicorn). The web server simply does what it’s configured to do. Nothing magical here.
Anyway. Django gets the request, processes it, maybe looks up some data in a database and sends out a response.
In more detail: Your Django app reacts to the request. The requested URL is interpreted using your urls.py configurations. The correct view is selected to handle the request. The view code might use a model to get data from the database, and renders out a template, passing data in a context object to it. Phew. This is what a “classical” Django project is. You get that out of the box, and this is a very good way to start for almost every web project out there.
The resulting HTML is packaged in a response. The response contains an HTML page inside of the HTTP body.
The browser receives the response, and renders the DOM from the HTML. From there, the browser probably makes more requests to load those puppy images and some CSS so it can style the page. Those resources are static, and should be handled as in the first example case.
Sprinkled in interactivity with jQuery, Vue.js or vanilla JS
Imagine, that a dynamic page is loaded from the backend, just as described in the previous example. The returned HTML contains
JS code inside a
The browser will render the page and start executing the JS code.
In this case, the code is only setting up some interactivity. Maybe to hide or show elements dynamically when a button is pressed, or to do on-demand communication with the backend.
The JS code, no matter which flavor, can ask for more requests to be sent to the backend. Fresh data can be requested this way, and the JS code takes care of handling it once it arrives without doing complete page reloads. HTTP requests triggered by JS code usually are made in the background.
We have the same page as before, but can trigger browser events without reloading the page. This makes for a more continuous user experience, as they don’t see the screen flash and new data loads smoothly, without breaking the UX flow.
Frontend framework integrated: Vue.js for example
Now we get into JS framework territory. This case is the same as above, but the template returned by the backend is not necessarily complete. Chunks of the final page are missing from the initial HTML response.
Instead, it contains JS code which is responsible for filling in the blanks. In the previous example, the HTML markup was complete, and JS was only adding some interactivity.
The effect is, that the final HTML which is shown to the user is not the one which leaves the server.
The browser takes care of executing JS code once the page arrives, which in turn builds the rest of the page. You can do this conveniently with Vue.js - read more here.
Single Page Application (SPA) - data is fetched afterwards
With the single-page-app architecture, a static page is loaded with a bunch of JS in it. Your backend code isn’t being used for this initial request. There’s nothing dynamic about it after all - it’s just about loading very simple HTML and fetching JS in the beginning.
The web server provides those. Django usually involved in serving the static assets in that case - the web server or another service such as AWS S3 takes care of those.
Once the HTML and JS has arrived at the browser, the JS is executed and starts making requests to the server for DATA. This is what the backend code provides - usually in the form of JSON responses.
In the previous case, the browser initially received an empty page with some JS linked from it.
As it turns out, this is something which search engines don’t like. They think those initially-empty pages are boring and this causes them to think less of your site.
They would much rather see a nice-looking, complete site.
This is what server-side rendering is for. The initial HTML and JS loaded on the server, and pre-rendered to HTML, but using frontend technology!
Essentially, there’s a part of the backend which pretends to be a browser for a while! It makes requests to your backend code and builds a HTML site by executing the JS part of the frontend code.
Once it’s done, the browser gets an HTML response, which was produced by JS code. The Django server is used to provide JSON data for that rendering step.
“Why all the hassle?” you may ask. Well, this is what you have to do if you want to have an SPA architecture, but still be friends with search engines.
Mainly, SSR is used for SEO reasons. It’s used to fix problems which are caused by delivering empty (or just incomplete), yet-to-be-assembled-by-JS HTML responses in the first place. There can be performance and caching upsides, but those usually don’t matter as much.
That’s it! I hope this article was useful to you, and you have a better overview of how the backend and the frontend communicate after reading it.
There are a lot of special cases, and things can get tricky, but in the end it’s only HTML and JSON going between the server and the user’s browser.
If you’re not sure which way to structure the communication between your frontend and backend - just keep it as simple as possible.
There’s no need to start out with a SPA from the get-go. You also don’t have to do heavy lifting inside of the frontend code. It’s great to have your backend responsible for building HTML responses, and get more fancy once you see the actual need to do so.
I hope this helped! Have fun building cool web applications, and connecting your frontends and backends with confidence.
If you have suggestions, comments or questions - drop me a mail via firstname.lastname@example.org. Always happy to hear from you :)