A historical look on web development
Preface: Why did I start writing this website
My primary reason for writing this website was simply that I was lacking another programming project, and I really wanted to write one. Also, doing frontend work has started to become really fun for me. It is fun to style a website so that it looks and feels just how you like it. While this website is super barebones in terms of styling, I nonetheless like it. The dark-mode/light-mode toggle is really nice. The green-ish color of links is really nice, at least in my opinion.
But there is one more big reason: All my previous websites (NonoJs and Bockscore) have been Single-Page Applications (SPA). For me, a complete frontend beginner, this seemed like the default way to write a website: Get a JavaScript-framework, follow some tutorials, do some AI prompting and make the website happen. So that's what I did. In retrospect, that was a mistake. On this page, I will show you why and give you a quick rundown of the history of web development.
A historical look on web development
Back in the 90s, when the web first came about, serving a website was super simple: First, you need a server that can understand HTTP-Requests. This sounds more complicated than it is. A basic HTTP-Request looks like this:
GET /index.html
This means "Send me the file /index.html." A basic HTTP server can simply read the request, see that it is a GET,
parse the path (maybe using splitString()) and serve the file.
Therefore, creating a website was as simple as creating a folder that might look like this:
- images/
- cat.png
- index.html
- style.css
- favicon.ico
Then you just run some HTTP-server like Apache or nginx, pointing it to the folder where your files are, and they will be served.
The server will automatically fetch index.html when requesting /, and all files linked in the HTML
using tags like <link> or <img> will be requested by the browser using additional GET-requests.
And then your website will be displayed, just how you like it.
This was the basic way on how to create websites. It was simple. Serving a website was very fast because the webserver does not need to do anything except read the request, then read the file from disk (frequently accessed files will be cached) and return it. Note that a single URL will always display the same content. If you want your users to see something different on the screen, you must navigate them to a different page by adding a link.
The static-file approach as described above is usually not good enough for even simple websites like this one. As an example, take a look at this websites Home Page and list of articles. The pages have different content, but the styling, the header and the script for the color scheme toggle is the same. Therefore, large parts of the HTML are reused between the sites. With a static file approach, I would have to copy-paste all required HTML for each page that I write and also for each article. If I wanted to change the header, I'd have to do it in all 100 files that contain the header.
The solution to that problem is to get rid of the static file approach and have a more sophisticated webserver.
The webserver receives a request to /articles, but instead of just serving a static articles.html-file,
it builds the requested page from scratch using templates, reusable components, data from a database and whatnot.
This website works just like that: All the pages seen here are written with PHP. PHP is a scripting language that you can embed into HTML. Here is a simple example snippet:
<span>This is some text.</span>
<?php for ($i = 0; $i < 5; $i++): ?>
<span>This is repeated five times.</span>
<?php endfor; ?>
<span>This is some other text.</span>
Very basic PHP, executed on the server.
Executing this using PHP will result in:
<span>This is some text.</span> <span>This is repeated five times.</span> <span>This is repeated five times.</span> <span>This is repeated five times.</span> <span>This is repeated five times.</span> <span>This is repeated five times.</span> <span>This is some other text.</span>The result, sent to the browser.
Of course you can do more things with PHP, it is a fully fledged programming language just like Java or C#. The important parts to remember here are:
-
A single
GET-request does not necessarily just serve some static file lying on disk. - Changing the content of the web page is only possible by navigating to another page. Once a page has been visited, the content is static.
/articles/about-this-page?theme=dark. But that does not happen.
JavaScript is another general purpose programming language, just like PHP. Your browser can execute JavaScript and change the content
of the page, without requiring a reload. JavaScript can be triggered when the page is loaded, a button is pressed, a selection is changed,
the mouse is moved, or any other of the million list of events.
In my case, changing the selection of the theme selector adds a data attribute to the root <html>-tag,
which is then used by CSS to change the color scheme.
The modern Single Page Application
A Single-Page Application (SPA) is a website that is interactive without ever having to change to a different page. The initial HTML sent by the webserver when requesting the page is mostly empty. Then, JavaScript runs and starts fetching data from the server. Based on that data, the JavaScript then builds the contents of the page. On user interaction, like clicking a button, JavaScript will trigger again and change the content of the page and maybe fetch some more data from the server.
The job of the server here is not anymore to build the requested web pages based on the URL. The server always just serves a single, mostly empty site containing the script that actually builds the site. Instead, the real job of the server is providing the data that is necessary to build the website. As an example, think of Amazon. Think of what happens when you search for "Lord of the Rings":
In the "old world", searching for "Lord of the Rings" would redirect you to a URL like
https://amazon.com/search?q=Lord+of+the+Rings. The search string is encoded in the URL. The web server gets the request,
reads the query string from the URL, searches its database for products matching "Lord of the Rings", sorts the result by
some ranking, and then builds the final HTML, creating one <div> per result.
The results page would be limited and only show 20 articles. If you want to see more, you would click on a link that
sends you to a URL like code>https://amazon.com/search?q=Lord+of+the+Rings&page=2.
This approach is called Server-Side Rendering (SSR), because it is the server that builds the full HTML.
In the "new world", with an SPA, this would be completely different. You would enter "Lord of the Rings" on the search input and click the button. Now, JavaScript will fire and send a search request to the server. This could look something like this:
GET /search?q=Lord+of+the+RingsThis looks similar to before. But this request is not fired because the browser opens a new page! The response alone will do nothing unless handled by JavaScript. The response is also not HTML, but an easy-to-read data exchange format like JSON. An example response could be:
{
"results": [
{
"name": "Lord of the Rings: The Fellowship of the Ring (Blu-Ray)",
"price": "9.99$"
},
{
"name": "Lord of the Rings (Book)",
"price": "34.99$"
},
// ...
]
}
You can see that the response is really easy to read and parse. Especially JSON, which is supported out-of-the-box by JavaScript anyway. Your JavaScript running in the browser will read the response and then replace the content of your page to display the results. In this world, the server is called the backend and the whole JavaScript that is communicating with the server and building your page is called the frontend.
You probably don't want a Single-Page Application
Despite the heading, SPAs have some advantages over traditional, server-rendered websites:
- Websites can feel like a real desktop application.
- Imagine an in-the-web Photoshop: Opening a menu or dialog should not redirect you to some other page, since that will make you lose the entire state of the current image.
- Also, redirects mean new page loads. With javascript, you can have interactivity without requiring any loads, thus making websites just as snappy as desktop applications.
- The server provides an easy-to-use API for the client out-of-the-box. This makes is possible to write new, alternative clients for a website.
- In the above SPA example, you could probably write a minimalistic Amazon search app within a couple of hours because the API is so simple. If the server instead just gave you finished HTML, you would be out of luck.
- The website is now inherently stateful, and the difficulty of programming such a website skyrockets.
- In the "old world", all the server had to do is calculate the HTML for a requested page.
- In the "new world", the frontend has to maintain the entire state of the website (e.g. what tab you are on, if you are in a search or on the home page, what settings you have chosen...) and has to make sure that what is displayed always matches the internal state.
-
By default, sharing links does not work: In the SPA example, executing a search does not navigate you anywhere.
Your browsers' URL will still be
http://www.amazon.com/. - Likewise, if you reload the page, the current state is lost and you will land on the startpage.
- Back and forward navigation also does not work for the same reason.
- Performance is usually quite a bit worse than with server-side rendering because it often takes multiple sequential HTTP requests to finish building the page.
- To understand this, think about the Amazon example again and imagine there is a 50ms latency between your computer and the Amazon server.
- With server-side rendering, you do one request to the server to get the HTML, and then multiple parallel requests to fetch all required resources such as images, stylesheets and more. Since all of those requests run in parallel, you only pay the latency cost once. Your page will have loaded after 100ms plus however long it takes to download all the images.
- With an SPA, you do one request for the inital HTML, which is mostly empty except for a linked script. Then you do one request to load the javascript. Then the javascript runs, building your initial page, probably making parallel requests to the server. And then finally the images and all required resources get loaded. In total, that is at least four sequential requests, meaning that it takes at least 200ms for your page to load.
- Often, in practice, quite a bit more sequential requests are required, slowing the page down.
So ask yourself: Do you want to write a website, or do you want to write an app that just so happens to be executed in a web browser? Writing a server-side rendered website using established technologies like PHP will probably make your website faster, snappier, easier to use and easier to build.
The conclusion
I have not written this article with the intention of hating on JavaScript frameworks, SPAs or similar. I have written this article because SPAs have become the defacto standard way of doing web development. Look up any YouTube video on web development or how to do frontend stuff and your feed will be full of videos showing you the power of the latest JavaScript framework. In reality, you might just need HTML, CSS and nginx.
I have also written this article to give a brief view into the interesting history of web development. As usual, the complicated webdev world that we know nowadays started from something very simple: Static HTML files served by a simple program that parses HTTP 1.0. I am certain that understanding the roots of web development and development to what we have now will give you a deeper understanding of web development as a whole and maybe puts the latest and shiniest frameworks into a little bit of context.
And by the way: Server-side rendering is making a comeback: Many modern webservers nowadays are written using JavaScript/TypeScript using Node.js, meaning that the rendering code that would work on your client would also just work on the server. Therefore new frontend devs can choose to do server-side rendering while still writing old familiar JavaScript.