The web is everywhere. What is the best way to create websites and develop applications? If you google „web development“, there are millions of hits. The opinions are so many, diverse, contradicting, and overwhelming.
When I was starting out and developing my first web application, my first impression of the structure of the web was very favorable. I appreciated the built-in and enforced separation of behavior from content (HTML) and styling (CSS).
However, my understanding of how to create a web application was that the entire application needed to be rendered in JavaScript in the client of the application. The client would then send periodic updates to the server and would update the page based on the responses. This is called a single-page application and there are several frameworks like React and Angular which standardize how they are supposed to be developed.
I found front-end development frustrating. If I changed one little thing in the front end, I would have to remember to change it in the back end. The same was the case if I changed something in the back end. It was increasingly complex, increasingly difficult to remember what I had done before. Eventually, I found it so frustrating that I quit. I was only going to do back-end development from that point on.
I distinctly remember the first time I rendered an HTML form in my web application. I had defined a click handler for the button in the form, but when I clicked on it, the whole application disappeared, and frustrated with this seemingly horrifying behavior, I turned to Stack Overflow for the answer.
Pretty soon I was adding event.preventDefault();
as the first line of every click handler that I ever wrote so that my application would not have any unexpected behavior.
How a form works
I did not understand what the default behavior of an HTML form was until I participated in our internal ROCA workshop. For some people this may seem completely obvious, but it was not for me, and in my experience, I am not the only one.
It turns out that HTML is not only meant as a markup language to describe how a page is structured. It also has semantics. The most common semantic element is a link:
Another very powerful semantic element in HTML is a form:
The default method for a form is the GET
method. This means that a form with only an action and a submit button is semantically identical to a link. However, a form also makes it possible to modify the query string for the url. The above form, if it were clicked, would send the following GET
request to the server: GET /example-uri?param1=Text+Field
Different input fields offer different semantics. A checkbox field
will generate the query string ?food=Cheese
only if the checkbox is selected.
If you use radio buttons in a form, the browser ensures that at maximum one of the options is selected.
A select element performs a similar function, but displays the values in a drop-down menu.
When you want to send a list of elements to the server, you can just give multiple inputs the same name.
This will then be translated as the query string ?order=Hamburger&order=Cheese
which will be interpreted by the server as a list of values.
Forms are, therefore, a way of specifying a request to the server. Once the form is submitted, the request is sent to the server and the server handles it.
Handling Requests on the Server
The second piece of the puzzle is handling the requests on the server. A form is simply a tool for constructing an HTTP request and sending it to the web server that is serving the web application. For this reason, to understand how a form works, it is important to understand the fundamentals of HTTP.
An HTTP request consists of a method (e.g. GET
) and a URI to a resource (e.g. /cat.png
). An HTTP server takes this request and decides what to do with it. Then it returns an HTTP response to the user which contains a status code and content. A web browser knows both how to send an HTTP request (via link or form) and how to handle the response that comes back from the server. The most common action will be to simply render the content of the response in the browser window. It is also possible to use URL redirection to navigate within the application.
By default, an HTML form only supports the GET
and POST
HTTP methods. According to the HTTP 1.1 Specification, GET
requests should only be used to retrieve resources, never to modify them. A POST
request, however, can be used to modify existing resources.
Other HTTP methods, like PUT
, DELETE
, and PATCH
can be very useful when creating RESTful services. Many web frameworks also provide for these HTTP methods by tunneling within a POST
request:
Even with all of this information, it might be difficult to conceptualize how such a web application could be constructed.
As an example, consider a web application for managing ebooks. By executing GET /books
, you would get an HTML page listing all of the books that you have added so far. You can also render an HTML form in the page, allowing you to add a book with POST /books?title=Title&author=Author&nrStars=4
. After adding the book, the application might redirect you back to the /books
page where you would see the new book rendered. The page might contain links to a particular book, GET /books/:bookid
, which would display more information about the book, and you could render forms in the page to allow you to update the book (PUT /books/:bookid
) or remove it from your library (DELETE /books/:bookid
).
Programming web pages in this way is old-fashioned. However, it is also tried and true and will work in every single browser, even if JavaScript is not available ([1],[2]). I can also say with relative certainty that it will continue working for the forseeable future.
Luckily for us, there are great web frameworks that are available to help us. Some of them include:
- Compojure in Clojure
- Rails in Ruby
- Spring Boot in Java
- Play in Scala and Java
- Phoenix in Elixir
- Express for Node.js
I still love the separation of behavior, content, and styling that is inherent in the web. However, the behavior of the web is not defined, as I once thought, using JavaScript. The behavior of a web application is defined by the web server that is serving the application. If I want to change the behavior of the application, I now only have to do it in one place.
So what do I use JavaScript for? Progressive Enhancement to improve the appearance of the website once it has been rendered. There are use cases where it is necessary to create a rich client in our web browser. If that is the case, then it might make sense to use something like React for the resource in our application that needs this. However, in the vast majority of cases, we simply don’t need it if we have a fundamental understanding of HTML forms and HTTP.
It is challenging and fun to create a website that works without JavaScript. It requires you to stretch your creative muscles. And most importantly, creating a webpage in this way will increase the platforms that your application can run on and make it more accessible for everybody to use.