mirror of
https://github.com/bigskysoftware/hypermedia-systems.git
synced 2025-12-05 00:03:55 -05:00
709 lines
41 KiB
Plaintext
709 lines
41 KiB
Plaintext
|
||
= Hypermedia: A Reintroduction
|
||
:chapter: 01
|
||
:url: ./hypermedia-reintroduction/
|
||
|
||
Hypermedia is a universal technology today, almost as common as electricity.
|
||
|
||
Billions of people use a hypermedia-based systems every day, mainly by interacting with the _HyperText Markup Language
|
||
(HTML)_ being exchanged via the _HyperText Transfer Protocol (HTTP)_ by using a Web Browser connected to the World Wide
|
||
Web.
|
||
|
||
People use these systems to get their news, check in on friends, buy things online, play games, send emails and so
|
||
forth: the variety and sheer number of online services being delivered by hypermedia is truly astonishing.
|
||
|
||
And yet, despite this ubiquity, the topic hypermedia itself is a strangely under-explored concept today, left mainly to
|
||
specialists. Yes, you can find a lot of tutorials on how to author HTML, create links and forms, etc. But it is rare
|
||
to see a discussion of HTML __as a hypermedia__ and, more broadly, on how an entire hypermedia _system_ fits together.
|
||
|
||
This is in contrast with the early web development era when concepts like _Representational State Transfer (REST)_
|
||
and _Hypermedia As The Engine of Application State (HATEOAS)_ were discussed frequently, refined and debated among
|
||
web developers.
|
||
|
||
In a sad turn of events, today, the world's most popular hypermedia, HTML, is often viewed resentfully: it is an
|
||
awkward, legacy markup language that must be grudgingly used to build user interfaces in what are
|
||
increasingly entirely Javascript-based web applications.
|
||
|
||
HTML happens to be there, in the browser, and so we have to use it.
|
||
|
||
This as a shame and we hope that with this book we can convince you that this hypermedia is _not_ simply a
|
||
piece of legacy technology that we have to accept and deal with. Instead, we aim to show you that hypermedia is a
|
||
tremendously innovative, simple and _flexible_ way to build robust applications: _Hypermedia-Driven Applications_.
|
||
|
||
We hope that by the end of this book you will feel, as we do, that the hypermedia approach deserves a seat at the table
|
||
when you, a web developer, are considering the architecture of your next application. Creating a Hypermedia-Driven
|
||
Application on top of a _hypermedia system_ like The Web is a viable and, indeed, often excellent choice for
|
||
_modern_ web applications.
|
||
|
||
(And, as the section on HyperView will show, not just web applications.)
|
||
|
||
== What Is Hypermedia?
|
||
|
||
[quote, Ted Nelson, https://archive.org/details/SelectedPapers1977/page/n7/mode/2up]
|
||
____
|
||
Hypertexts: new forms of writing, appearing on computer screens, that will branch or perform at the reader’s
|
||
command. A hypertext is a non-sequential piece of writing; only the computer display makes it practical.
|
||
____
|
||
|
||
Let us begin at the beginning: what is hypermedia?
|
||
|
||
Hypermedia is a media, for example a text, that includes _non-linear branching_ from one location in the media to another,
|
||
via, for example, hyperlinks embedded in the media. The prefix "`hyper-`" derives from the Greek prefix "`ὑπερ-`" which
|
||
means "`beyond`" or "`over`", indicating that hypermedia _goes beyond_ normal, passively consumed media like magazines and
|
||
newspapers.
|
||
|
||
Hyperlinks are a canonical example of what is called a _hypermedia control_:
|
||
|
||
Hypermedia Control:: A _hypermedia control_ is an element in a hypermedia that describes (or controls) some sort of
|
||
interaction, often with a remote server, by encoding information about that interaction directly and completely within
|
||
itself.
|
||
|
||
It is hypermedia controls that differentiate hypermedia from other sorts of media.
|
||
|
||
You may be more familiar with the term _hypertext_, from whose Wikipedia page the above quote is taken. Hypertext
|
||
is a sub-category of hypermedia and much of this book is going to discuss how to build modern applications using
|
||
hypertexts such as HTML, the HyperText Markup Language, or HXML, a hypertext used by the HyperView mobile hypermedia
|
||
system.
|
||
|
||
Hypertexts like HTML function along-side other technologies crucial for making an entire hypermedia system work: network
|
||
protocols like HTTP, other media types such as images, videos, hypermedia servers (i.e. servers providing hypermedia APIs),
|
||
sophisticated hypermedia clients (e.g. web browsers), and so on.
|
||
|
||
Because of this, we prefer the broader term _hypermedia systems_ when describing the underlying architecture of
|
||
applications built using hypertext, to emphasize the system architecture over the particular hypermedia being used.
|
||
|
||
It is the entire hypermedia _system architecture_ that is underappreciated and ignored by many modern web developers.
|
||
|
||
== A Brief History of Hypermedia
|
||
|
||
Where did the idea of hypermedia come from?
|
||
|
||
While there were many precursors to the modern idea of hypertext and the more general hypermedia, many people point
|
||
to the article _As We May Think_ written by Vannevar Bush in The Atlantic as a starting point for looking at what
|
||
has become modern hypermedia.
|
||
|
||
In this article Bush described a device called a Memex, which, using a complex mechanical system of reels and microfilm,
|
||
along with an encoding system, would allow users to jump between related frames of content. The Memex was never actually
|
||
implemented, but it was an inspiration for later work on the idea of hypermedia.
|
||
|
||
The terms "`hypertext`" and "`hypermedia`" were coined in 1963 by Ted Nelson, who would go on to work on the _Hypertext Editing
|
||
System_ at Brown University and who later created the _File Retrieval and Editing System (FRESS)_, a shockingly advanced
|
||
hypermedia system for its time. (This was perhaps the first digital system to have a notion of "`undo`".)
|
||
|
||
While Nelson was working on his ideas, Douglas Engelbart was busy at work at the Stanford Research Institute, explicitly
|
||
attempting to make Vannevar Bush's Memex a reality. In 1968, Englebart gave "`The Mother of All Demos`" in San Francisco,
|
||
California.
|
||
|
||
Englebart demonstrated an unbelievable amount of technology:
|
||
|
||
* Remote, collaborative text editing with his peers in Menlo Park
|
||
* Video and audio chat
|
||
* An integrated windowing system, with window resizing, etc.
|
||
* A recognizable hypertext, whereby clicking on underlined text navigated to new content
|
||
|
||
Despite receiving a standing ovation from a shocked audience after his talk, it was decades before the technologies
|
||
Englebart demonstrated became mainstream.
|
||
|
||
=== Modern Implementation
|
||
|
||
In 1990, Tim Berners-Lee, working at CERN, published the first website. He had been working on the idea of hypertext
|
||
for a decade and was finally, out of desperation at the fact it was so hard for researchers to share their research,
|
||
found the right moment and institutional support to create the World Wide Web:
|
||
|
||
[quote, Tim Berners-Lee, https://britishheritage.org/tim-berners-lee-the-world-wide-web]
|
||
____
|
||
Creating the web was really an act of desperation, because the situation without it was very difficult when I was working
|
||
at CERN later. Most of the technology involved in the web, like the hypertext, like the Internet, multifont text objects, had all
|
||
been designed already. I just had to put them together. It was a step of generalising, going to a higher level of abstraction,
|
||
thinking about all the documentation systems out there as being possibly part of a larger imaginary documentation system.
|
||
____
|
||
|
||
By 1994 The Web had grown so quickly that Berners-Lee founded the W3C, a working group of companies and researchers
|
||
tasked with improving The Web. All standards created by the W3C were royalty-free and could be adopted and implemented
|
||
by anyone, cementing the open, collaborative nature of The Web.
|
||
|
||
In 2000, Roy Fielding, then at U.C. Irvine, published a seminal PhD dissertation on The Web: "`Architectural Styles and the
|
||
Design of Network-based Software Architectures`". Fielding had been working on the open source Apache HTTP Server and
|
||
his thesis was a description of what he felt was a _new and distinct networking architecture_ that had emerged in the early
|
||
web. Fielding had worked on the initial HTTP specifications and, in the paper, defined the web's hypermedia
|
||
network model using the term _REpresentational State Transfer (REST)_.
|
||
|
||
Fielding's dissertation became a major touchstone for early web developers, giving them a language to discuss the new technical
|
||
medium they were building applications in.
|
||
|
||
We will discuss Fielding's dissertation in depth in Chapter 3, and try to correct the record with respect to REST,
|
||
HATEOAS and hypermedia.
|
||
|
||
== The World's Most Successful Hypertext: HTML
|
||
|
||
[quote, Rescuing REST From the API Winter, https://intercoolerjs.org/2016/01/18/rescuing-rest.html]
|
||
____
|
||
In the beginning was the hyperlink, and the hyperlink was with the web, and the hyperlink was the web. And it was good.
|
||
____
|
||
|
||
The system that Lee, Fielding and many others had created revolved around a hypermedia: HTML. HTML started as a read-only
|
||
hypermedia, used to publish (at first) academic documents. These documents were linked together via anchor tags which
|
||
created _hyperlinks_ between them, allowing users of The Web to quickly navigate between documents.
|
||
|
||
When HTML 2.0 was released, it introduced the notion of the `form` tag, joining the anchor tag (i.e. hyperlink) as a
|
||
second hypermedia control. The introduction of the form tag made building _applications_ on The Web viable by providing
|
||
a mechanism for _updating_ resources, rather than just reading them.
|
||
|
||
It was at this point that The Web transitioned from an interesting document-oriented system to a compelling
|
||
_application architecture_.
|
||
|
||
Today HTML is the most widely used hypermedia in existence and this book naturally assumes that the reader has a
|
||
reasonable familiarity with it. You do not need to be an HTML (or CSS) expert to understand the code in this book, but
|
||
the better you understand the core tags and concepts of HTML, the more you will get out of it.
|
||
|
||
=== The Essence of HTML as a Hypermedia
|
||
|
||
Let us consider these two defining hypermedia elements (that is the two defining _hypermedia controls_) of HTML,
|
||
the anchor tag and the form tag, in a bit of detail.
|
||
|
||
==== Anchor Tags
|
||
|
||
Anchor tags are so familiar as to be boring but, as the original hypermedia control, it is worth reviewing the mechanics
|
||
of hyperlinks to get our minds in the right place for developing a deeper understanding of hypermedia.
|
||
|
||
Consider a simple anchor tag, embedded within a larger HTML document:
|
||
|
||
.A Simple Hyperlink
|
||
[source,html]
|
||
----
|
||
<a href="https://hypermedia.systems/">
|
||
Hypermedia Systems
|
||
</a>
|
||
----
|
||
|
||
An anchor tag consists of the tag itself (i.e. `<a></a>`) as well as attributes and content within the tag. Of particular
|
||
interest is the `href` attribute, which specifies a _hypertext reference_ to another document (or fragment, etc.) It
|
||
is this attribute that makes the anchor tag a hypermedia control.
|
||
|
||
In a typical Web browser, this anchor tag would be interpreted to mean:
|
||
|
||
- Show the text "`Hypermedia Systems`" in a manner indicating that it is clickable
|
||
- When the user clicks on that text, issue an HTTP `GET` request to the URL `https://hypermedia.systems/`
|
||
- Take the HTML content in the body of the HTTP response to this request and replace the entire screen in the browser as a new
|
||
document, updating the navigation bar to this new URL
|
||
|
||
Anchors provide the main mechanism we use to navigate around the web today, by selecting links to navigate from document
|
||
to document (or from resource to resource).
|
||
|
||
Here is what a user interaction with an anchor tag/hyperlink looks like in visual form:
|
||
|
||
// TODO REDO IMAGE
|
||
.An HTTP GET In Action
|
||
image::figure_1-1_http_mental_model_get.txt.svg[]
|
||
|
||
When the link is clicked the browser (or, as we sometimes refer to it, the _hypermedia client_) initiates an HTTP
|
||
`GET` request to the given URL encoded `href` attribute of the link.
|
||
|
||
Note that the HTTP request includes additional data (i.e. _metadata_) on what, exactly, the browser wants from the server,
|
||
in the form of headers. We will discuss these headers, and HTTP in more depth in Chapter 3.
|
||
|
||
The _hypermedia server_ then responds to this request with a _hypermedia response_, that is, with the HTML for the new page.
|
||
This may seem like a small and obvious point, but it is an absolutely crucial aspect of a truly REST-ful _hypermedia
|
||
system_: the client and server must communicate via hypermedia!
|
||
|
||
==== Form Tags
|
||
|
||
Anchor tags provide _navigation_ between documents (or resources) but don't allow you to update them. That functionality
|
||
falls to the form tag.
|
||
|
||
Here is a simple example of a form in HTML:
|
||
|
||
[#listing-1-2, reftext={chapter}.{counter:listing}]
|
||
.A Simple Form
|
||
[source,html]
|
||
----
|
||
<form action="/signup" method="post">
|
||
<input type="text" name="email" placeholder="Enter Email To Sign Up..."/>
|
||
<button>Sign Up</button>
|
||
</form>
|
||
----
|
||
|
||
Like an anchor tag, a form tag consists of the tag itself (i.e. `<form></form>`) combined with attributes and then
|
||
content within the tag. Note that the form tag does not have an `href` attribute, bur rather has an `action` attribute
|
||
that specifies where to issue an HTTP request to.
|
||
|
||
Furthermore, it also has a `method` attribute, which specifies exactly which HTTP "`Method`" to use. In this example
|
||
the form is asking the browser to issue a `POST` request.
|
||
|
||
The content _within_ the form is more important than the content within an anchor tag is. The values of `input` tags
|
||
and other tags such as `select` tags will be included with the HTTP request when the form is submitted. This allows a
|
||
form to include an arbitrary amount of information collected from a user in a request, which is in contrast with the
|
||
anchor tag.
|
||
|
||
In a typical browser this form tag and its contents would be interpreted by the browser roughly as follows:
|
||
|
||
- Show a text input and a "`Sign Up`" button to the user
|
||
- When the user submits the form by clicking the "`Sign Up`" button or by hitting the enter key while the input element is
|
||
focused, issue an HTTP `POST` request to the path `/signup` on the "`current`" server
|
||
- Take the HTML content in the body of the HTTP response body and replace the entire screen in the browser as a new
|
||
document, updating the navigation bar to this new URL
|
||
|
||
This mechanism allows the user to issue requests to _update the state_ of resources on the server. Note that despite
|
||
this new type of request the communication between client and server is still done entirely with _hypermedia_.
|
||
|
||
It is the form tag that makes Hypermedia-Driven Applications possible.
|
||
|
||
If you are an experienced web developer you probably recognize that we are omitting a few details and complications
|
||
here. For example, the response to a form submission often _redirects_ the client to a different URL.
|
||
|
||
This is true, and we will get down into the muck with forms in more detail in later chapters but, for now, this simple
|
||
example suffices to demonstrate the core mechanism for updating system state purely within hypermedia.
|
||
|
||
Here is a diagram of the interaction:
|
||
|
||
// TODO update, needs to omit the 302 redirect
|
||
[#figure-1-2, reftext="Figure {chapter}.{counter:figure}"]
|
||
.An HTTP POST In Action
|
||
image::figure_1-1_http_mental_model_post.png[]
|
||
|
||
==== Web 1.0 Applications
|
||
|
||
As someone interested in web development the above diagrams and discussion probably look very familiar to you. You may
|
||
even find this content boring. But take a step back and consider the fact that these two hypermedia controls,
|
||
anchors and forms, are really the _only_ native ways for a user to interact with a server in plain HTML.
|
||
|
||
Only two tags!
|
||
|
||
And yet, armed with only these two tags, the early web was able to grow exponentially and offer a staggeringly large
|
||
amount of online, dynamic functionality to billions of people.
|
||
|
||
This is strong evidence of the power of hypermedia. Even today, in a web development world increasingly dominated by large
|
||
JavaScript-centric front end frameworks, many people choose to use simple vanilla HTML to achieve their application goals
|
||
and are often perfectly happy with the results.
|
||
|
||
These two tags give a tremendous amount of expressive power to HTML.
|
||
|
||
=== So What _Isn't_ Hypermedia?
|
||
|
||
So these are the two main hypermedia-based mechanisms for interacting with a server available in HTML.
|
||
|
||
Now let's consider a different approach: let's interact with a server by issuing an HTTP request via JavaScript. To
|
||
do this, we will use the https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API[`fetch()`] API, a popular API for
|
||
issuing an "`Asynchronous JavaScript and XML`", or AJAX request, available in all modern web browsers:
|
||
|
||
[#listing-1-3, reftext={chapter}.{counter:listing}]
|
||
.Javascript
|
||
[source,html]
|
||
----
|
||
<button onclick="fetch('/api/v1/contacts/1') <1>
|
||
.then(response => response.json()) <2>
|
||
.then(data => updateUI(data))"> <3>
|
||
Fetch Contacts
|
||
</button>
|
||
----
|
||
<1> Issue the request
|
||
<2> Convert the response to a JavaScript object
|
||
<3> Invoke the `updateUI()` function with the object
|
||
|
||
This button has an `onclick` attribute which specifies some JavaScript to run when the button is clicked.
|
||
|
||
The JavaScript will issue an AJAX HTTP `GET` request to `/api/v1/contacts/1` using `fetch()`. An AJAX request is like a
|
||
"`normal`" HTTP request in many ways, but it is issued "`behind the scenes`" by the browser. The user does not see a
|
||
request indicator by the browser like they would with normal links and forms, and, unlike with requests issued by
|
||
those hypermedia controls, it is up to the JavaScript code to handle the response from the server.
|
||
|
||
Despite AJAX having XML as part of its acronym, today the HTTP response to this request would almost certainly be in the
|
||
JavaScript Object Notation (JSON) format rather than XML.
|
||
|
||
An HTTP response to this request might look something like this:
|
||
|
||
[#listing-1-3, reftext={chapter}.{counter:listing}]
|
||
.JSON
|
||
[source,json]
|
||
----
|
||
{ <1>
|
||
"id": 42, <2>
|
||
"email" : "json-example@example.org" <3>
|
||
}
|
||
----
|
||
<1> The start of a JSON object
|
||
<2> A property, in this case with the name `id` and the value `42`
|
||
<3> Another property, the email of the contact with this id
|
||
|
||
The JavaScript code above converts the JSON text received from the server into a JavaScript object by calling the
|
||
`json()` method on it. This produces a JavaScript object. This object is then handed off to the `updateUI()` method.
|
||
|
||
The `updateUI()` method is then responsible for updating the UI based on the data that has been received from the server,
|
||
perhaps displaying this contact in a bit of HTML generated via a client-side template in the JavaScript application.
|
||
|
||
The details of exactly what the `updateUI()` function does aren't important for our discussion.
|
||
|
||
What _is_ important, what is the _crucial_ aspect of this JSON-based server interaction is that it is _not_ using
|
||
hypermedia. The JSON API being used here does not return a hypermedia response. There are no _hyperlinks_ or other
|
||
hypermedia-style controls in it.
|
||
|
||
This JSON API is, rather, a _Data API_.
|
||
|
||
Because the response is in JSON and is _not_ hypermedia, the JavaScript `updateUI()` method must understand how to turn
|
||
this contact data into HTML.
|
||
|
||
In particular, the code in `updateUI()` needs to know about the _internal structure_ and meaning of the data.
|
||
|
||
It needs to know:
|
||
|
||
- Exactly how the fields in the JSON data object are structured and named
|
||
- How they relate to one another
|
||
- How to update the local data this new data corresponds with
|
||
- How to render this data to the browser
|
||
- What additional actions/API end points can be called with this data
|
||
|
||
In short, the logic in `updateUI()` needs to have intimate knowledge of the API endpoint at `/api/v1/contact/1`, provided
|
||
via some side-channel beyond the response itself. Because of this, it can be said that the `updateUI()` code and the
|
||
API are _tightly coupled_: if the format of the JSON response changes, then the code for `updateUI()` will almost certainly
|
||
also need to be changed.
|
||
|
||
==== Single Page Applications
|
||
|
||
This bit of JavaScript, while very modest, is the organic beginnings of a much larger conceptual approach to building
|
||
web applications. This is the beginning of a _Single Page Application (SPA)_. The web application is no longer
|
||
navigating _between_ pages using hypermedia controls as was the case with links and forms.
|
||
|
||
Instead, the application is exchanging _plain data_ with the server and then updating the content _within_ a single page.
|
||
|
||
When this strategy (or architecture) is adopted for an entire application, everything happens on a "`Single Page`" and,
|
||
thus the application becomes a "`Single Page Application.`"
|
||
|
||
This Single Page Application architecture is extremely popular today and has been the dominant (at least in terms of
|
||
mind-share and blog posts) approach to building web applications for the last decade.
|
||
|
||
Today the vast majority of Single Page Applications adopt far more sophisticated frameworks for managing their
|
||
user interface than this simple example shows. Popular libraries such as React, Angular, Vue.js, etc. are all common,
|
||
and, indeed, the standard way to build web applications.
|
||
|
||
With these more complex frameworks developers typically work with an elaborate client-side model (that is, JavaScript objects
|
||
stored locally in the browser's memory that represent the "`model`" or "`domain`" of your application.) These JavaScript objects
|
||
are updated via JavaScript code and the framework then "`reacts`" to these changes, updating the user interface.
|
||
|
||
When the user interface is updated by a user these changes also flow _into_ the model objects, establishing a "`two-way`"
|
||
binding mechanism: the model can update the UI and the UI can update the model.
|
||
|
||
All very sophisticated and, today, very popular. But the fact is that developers that adopt this approach to building
|
||
web applications have largely abandoned the underlying hypermedia system of The Web.
|
||
|
||
HTML is still used to build user interfaces, but the _hypermedia_ aspect of the two major hypermedia controls,
|
||
anchors and forms, are ignored. Neither tag interacts with a server via their native _hypermedia_ mechanism. Rather,
|
||
they become mere user interface elements that drive local interactions with the in-memory domain model via JavaScript,
|
||
which is then synchronized with the server using plain data JSON APIs.
|
||
|
||
So, like our simple button above, the Single Page Application approach is _not_ built on top of a hypermedia architecture.
|
||
It does not take advantage of the natural REST-ful architecture of The Web, nor does it utilize the built-in functionality
|
||
found in HTML's native hypermedia controls.
|
||
|
||
SPAs are, in some sense, much more akin to _thick client applications_ like the client-server applications of the
|
||
1980s, which popular _before_ The Web came along.
|
||
|
||
This isn't a _necessarily wrong approach_, but it is worth thinking about _why_ web developers so frequently take it and
|
||
if there are reasons _not_ to go down this path.
|
||
|
||
== Why Use Hypermedia?
|
||
|
||
[quote, Tom MacWright, https://macwright.com/2020/05/10/spa-fatigue.html]
|
||
____
|
||
The emerging norm for web development is to build a React single-page application, with server rendering. The two key
|
||
elements of this architecture are something like:
|
||
|
||
1. The main UI is built & updated in JavaScript using React or something similar.
|
||
2. The backend is an API that that application makes requests against.
|
||
|
||
This idea has really swept the internet. It started with a few major popular websites and has crept into corners like
|
||
marketing sites and blogs.
|
||
____
|
||
|
||
The JavaScript-based Single Page Application approach has taken the web development world by storm, and there was one
|
||
major and very good reason for its success: The Single Page Application offers a far more interactive and immersive experience
|
||
than the old, gronky, Web 1.0 hypermedia-based applications could. The ability to smoothly update elements inline on
|
||
a page without a dramatic reload of the entire document, the ability to use CSS transitions to create nice visual easements,
|
||
the ability to hook into arbitrary events like mouse movements, all gave JavaScript-based applications a huge advantage
|
||
in building sophisticated user experiences.
|
||
|
||
So why on earth would you abandon this popular and modern approach for an older, less popular and much less discussed
|
||
approach such as hypermedia?
|
||
|
||
=== JavaScript Fatigue
|
||
|
||
Well, we are glad you asked.
|
||
|
||
It turns out that the hypermedia architecture, even in its original Web 1.0 form, has a number of advantages when compared with
|
||
the Single Page Application + JSON Data API approach:
|
||
|
||
* It is an extremely simple approach to building web applications
|
||
|
||
* It is extremely tolerant of content and API changes (in fact, it thrives on them!)
|
||
|
||
* It leverages tried and true features of web browsers, such as caching
|
||
|
||
The first two advantages, in particular, address major pain points in modern web development:
|
||
|
||
* Single Page Application infrastructure has become extremely complex, often requiring an entire team to manage
|
||
|
||
* JSON API churn, constant changes made to JSON APIs to support application needs, has become a major pain point for
|
||
many application teams
|
||
|
||
These two problems, combined with other various issues such as JavaScript library churn, are causing what has come to
|
||
be known as "`Javascript Fatigue`": a general sense of exhaustion with all the hoops that are necessary to jump through to
|
||
get anything done in modern-day web applications.
|
||
|
||
We believe that a hypermedia architecture can help cure Javascript Fatigue for many developers and teams. On the other
|
||
hand, however, if hypermedia is so great and if it addresses so many of the problems that obviously beset the web
|
||
development industry, why was hypermedia abandoned in the first place? After all, hypermedia was there first.
|
||
|
||
Why didn't web developers just stick with it?
|
||
|
||
We believe that hypermedia hasn't made a comeback yet for two reasons.
|
||
|
||
The first is this: the expressiveness of HTML _as a hypermedia_ hasn't changed much, if at all, since HTML 2.0, which
|
||
was released _in the mid 1990s_. Many new _features_ have been added to HTML, of course, but there haven't been _any_
|
||
major new ways to interact with a server in HTML added in almost three decades.
|
||
|
||
HTML developers still only have anchor tags and forms available as hypermedia controls, and those hypermedia controls
|
||
can still only issue `GET` and `POST` requests.
|
||
|
||
This baffling lack of progress by HTML leads immediately to the second, and perhaps more practical reason that
|
||
HTML-as-hypermedia has fallen on hard times: as the interactivity and expressiveness of HTML has remained frozen, the
|
||
demands from web users has continued to increase, demanding more and more interactive web applications.
|
||
|
||
JavaScript-based applications coupled to data-oriented JSON APIs has stepped in as a way to provide these more
|
||
sophisticated user interfaces for web applications. It was the _user experience_ that you could achieve in JavaScript
|
||
(and that you couldn't achieve in plain HTML) that drove the web development community over to the JavaScript-based
|
||
Single Page Application approach, rather than a superiority of the Single Page Application approach as a system
|
||
architecture.
|
||
|
||
It didn't have to be this way. There is nothing _intrinsic_ to the idea of hypermedia that prevents it from having a
|
||
richer, more expressive interactivity model than what vanilla HTML provides. Rather than abandoning
|
||
the hypermedia architecture the industry could have demanded more interactivity from HTML.
|
||
|
||
But the industry didn't. Instead, it reverted to making thick-client style applications within web browsers, in an
|
||
understandable move to a more familiar model for building rich applications.
|
||
|
||
Not everyone abandoned hypermedia, of course. There have been heroic efforts to continue to advance hypermedia outside of
|
||
HTML, efforts like HyTime, VoiceXML, and HAL.
|
||
|
||
But HTML, the most widely used hypermedia in the world, stopped making progress as a hypermedia and the web development
|
||
world moved on, solving the interactivity problems with HTML and, wittingly or not, adopting a completely different
|
||
system architecture along the way.
|
||
|
||
== A Hypermedia Resurgence?
|
||
|
||
It is interesting to think about how HTML _could_ have advanced. Instead of stalling as a hypermedia, how could HTML
|
||
have continued to develop? Could it have kept adding new hypermedia controls and increasing the expressiveness of
|
||
existing ones? Would it have become possible to build modern web applications within this original, hypermedia-oriented
|
||
and REST-ful model that made the early web so powerful, so flexible, so... fun?
|
||
|
||
This might seem like idle speculation, but we have some good news on this score: in the last decade a few
|
||
idiosyncratic, alternative front end libraries have arisen that attempt to get HTML moving again. Ironically these
|
||
libraries are written in JavaScript, the technology that supplanted HTML as the center of web development.
|
||
|
||
However, these libraries use JavaScript not as a __replacement__ for the fundamental hypermedia system of The Web.
|
||
|
||
Instead, they use JavaScript to augment HTML itself _as a hypermedia_.
|
||
|
||
These _hypermedia-oriented_ libraries re-center hypermedia as the core technology in web applications.
|
||
|
||
=== Hypermedia-Oriented Javascript Libraries
|
||
|
||
In the web development world today there is a debate going on between the SPA approach and what are now being called
|
||
"`Multi-Page Applications`" or MPAs. MPA is a modern name for the old, Web 1.0 way of building web applications, using
|
||
links and forms located on multiple web pages, submitting HTTP requests and getting HTML responses.
|
||
|
||
MPA applications, by their nature, are Hypermedia-Driven Applications: after all, they are exactly what Roy Fielding
|
||
was describing in his dissertation.
|
||
|
||
These applications tend to be clunky but, despite this, they work reasonably well. Many web developers and teams have
|
||
decided to just accept the limitations of plain HTML in the interest of the simplicity and reliability that it offers.
|
||
|
||
Rich Harris, creator of svelte.js, a popular SPA library, and a thought-leader on the SPA side of the debate, has proposed a mix
|
||
of this older MPA style and the newer SPA style. Harris calls this approach to building web applications "`transitional`", in that
|
||
it attempts to mix both the MPA approach and the newer SPA approach into a coherent whole. (This is somewhat
|
||
similar to the "`transitional`" trend in architecture, which blends traditional and modern architectural styles together.)
|
||
|
||
"`Transitional`" a good term for these mixed-style applications and offers a reasonable compromise between the two, using
|
||
either approach where it makes the most sense on an ad hoc basis.
|
||
|
||
But this compromise still feels unsatisfactory.
|
||
|
||
Why have these two very different architectural models _by default_?
|
||
|
||
Recall that the crux of the tradeoffs between SPAs and MPAs is the _user experience_, or interactivity of the application.
|
||
This is typically the driving decision when choosing one approach versus the other for an application or, in the case
|
||
of a "`transitional`" application, for a particular feature.
|
||
|
||
It turns out that by adopting a hypermedia-oriented library, the interactivity gap between the MPA and the SPA approach
|
||
closes dramatically. You can use the MPA approach, that is, the hypermedia approach, for much more of your application
|
||
without compromising your user interface. You might even be able to use the hypermedia approach for all your application
|
||
needs.
|
||
|
||
Rather than having an SPA with a bit of hypermedia around the edges, or some mix of the two approaches, you can often create
|
||
a web application that is _primarily_ or _entirely_ hypermedia driven, and that still satisfies the interactivity that your
|
||
users require.
|
||
|
||
This can _tremendously_ simplify your web application and produce a much more coherent and understandable piece of
|
||
software. There are still times and places for the more complex SPA approach, and we will discuss those later in the book,
|
||
but by adopting a hypermedia-first approach and using a hypermedia-oriented library to push HTML as far as possible,
|
||
your web application can be powerful, interactive _and_ simple.
|
||
|
||
One such hypermedia oriented library is https://htmx.org[htmx], created by the authors of this book. htmx will be the
|
||
focus of much (but not all!) of the remainder of this book. We hope to show you that you can, in fact, create many common
|
||
"`modern`" UI features found in sophisticated Single Page Applications using the hypermedia model.
|
||
|
||
And not only that, but that it is refreshingly fun and simple to do so.
|
||
|
||
=== Hypermedia-Driven Applications
|
||
|
||
When building a web application with htmx the term Multi-Page Application applies _roughly_, but it doesn't really capture
|
||
the crux of the application architecture. htmx, as you will see, doesn't _need_ to replace entire pages and, in fact, an
|
||
htmx-based application can reside entirely within a single page. We certainly don't recommend this practice, but it is
|
||
possible!
|
||
|
||
So it isn't quite right to call web applications build with htmx "Multi-Page Applications". What the older Web 1.0 MPA
|
||
approach and the newer hypermedia-oriented library powered applications have in common is their use of _hypermedia_ as
|
||
their core technology and architecture.
|
||
|
||
Therefore, we use the term _Hypermedia-Driven Applications (HDAs)_ to describe both.
|
||
|
||
This clarifies that the core distinction between these two approaches and the SPA approach _isn't_ the number of pages
|
||
in the application, but rather the underlying _system_ architecture.
|
||
|
||
Hypermedia-Driven Application (HDA):: A web application that uses _hypermedia_ and _hypermedia exchanges_ as its primary
|
||
mechanism for communicating with a server.
|
||
|
||
So, what does an HDA look like "`in the small`"?
|
||
|
||
Let's look at a htmx-powered implementation of the simple JavaScript-powered button above:
|
||
|
||
[#listing-1-4, reftext={chapter}.{counter:listing}]
|
||
.an htmx implementation
|
||
[source,html]
|
||
----
|
||
<button hx-get="/contacts/1" hx-target="#contact-ui"> <1>
|
||
Fetch Contact
|
||
</button>
|
||
----
|
||
<1> issues a `GET` request to `/contacts/1`, replacing the `contact-table`
|
||
|
||
As with the JavaScript powered button we can see that this button has been annotated with some attributes. However, in
|
||
this case we do not have any JavaScript scripting going on.
|
||
|
||
Instead, we have _declarative_ attributes much like the `href` attribute on anchor tags and the `action` attribute on
|
||
form tags. The `hx-get` attribute tells htmx: "`When the user clicks this button, issue a `GET` request to `/contacts/1``".
|
||
The `hx-target` attribute tells htmx: "`When the response returns, take the resulting HTML and place it into the element
|
||
with the id `contact-ui``".
|
||
|
||
Here we get to the crux of htmx and how it allows you to build Hypermedia-Driven Applications:
|
||
|
||
_The HTTP response from the server is expected to be in HTML format, not JSON_
|
||
|
||
This means that this htmx-powered button is exchanging _hypermedia_ with the server, just like an anchor tag or form
|
||
might, and thus the interaction is still within this original hypermedia model of The Web. htmx _is_ adding functionality
|
||
to this button (via JavaScript), but that functionality is _augmenting_ HTML as a hypermedia, extending the hypermedia
|
||
system of The Web, rather than _replacing_ that hypermedia system with a totally different architecture.
|
||
|
||
Despite looking superficially similar to one another it turns out that this htmx-powered button and the JavaScript-based
|
||
button are using extremely different system architectures and, thus, approaches to web development.
|
||
|
||
As we walk through building a Hypermedia-Driven Application in this book, the differences between the two approaches
|
||
will become more and more apparent.
|
||
|
||
== When Should You Use Hypermedia?
|
||
|
||
Hypermedia is often, though _not always_, a great choice for a web application.
|
||
|
||
Perhaps you are building a website or application that simply doesn't _need_ a huge amount of user-interactivity. There are
|
||
many useful web applications like this, and there is no shame in it! Applications like Amazon, Ebay, any number of news
|
||
sites, shopping sites, message boards and so on don't need a massive amount of interactivity to be effective: they are
|
||
mainly text and images, which is exactly what The Web was designed for.
|
||
|
||
Perhaps your application adds most of its value on the _server side_, by coordinating users or by applying sophisticated
|
||
data analysis and then presenting it to a user. Perhaps your application adds value by simply sitting in front of a
|
||
well-designed database, with simple Create-Read-Update-Delete (CRUD) operations. Again, there is no shame in this!
|
||
|
||
In any of these cases, using a hypermedia approach would likely be a great choice: the interactivity needs of
|
||
these applications are not dramatic, and much of the value of these applications lives on the server side, rather than on the client side.
|
||
|
||
All of these applications are amenable to what Roy Fielding called "`large-grain hypermedia data transfers`": you can simply
|
||
use anchor tags and forms, with responses that return entire HTML documents from requests, and things will work just fine.
|
||
This is exactly what the web was designed to do!
|
||
|
||
By adopting the hypermedia approach for these applications, you will save yourself a huge amount of client-side complexity
|
||
that comes with adopting the Single Page Application approach: there is no need for client-side routing, for managing
|
||
a client side model, for hand-wiring in JavaScript logic, and so forth. The back button will "`just work`". Deep linking
|
||
will "`just work`". You will be able to focus your efforts on your server, where your application is actually adding value.
|
||
|
||
And, by layering htmx or another hypermedia-oriented library on top of this approach, you can address many of the usability
|
||
issues that come with vanilla HTML and take advantage of finer-grained hypermedia transfers. This opens up a whole slew of new
|
||
user interface and experience possibilities, making the set of applications that can be built using hypermedia _much_ larger.
|
||
|
||
But more on that later.
|
||
|
||
== When Shouldn't You Use Hypermedia?
|
||
|
||
So, what about that _not always_? When isn't hypermedia going to work well for an application?
|
||
|
||
One example that springs immediately to mind is an online spreadsheet application. In the case of a spreadsheet,
|
||
updating one cell could have a large number of cascading changes that need to be made across the entire sheet. Worse,
|
||
this might need to happen _on every keystroke_.
|
||
|
||
In this case we have a highly dynamic user interface without clear boundaries as to what might need to be updated given
|
||
a particular change. Introducing a hypermedia-style server round-trip on every cell change would hurt performance
|
||
tremendously.
|
||
|
||
This is simply not a situation amenable to the "`large-grain hypermedia data transfer`" approach of The Web. For an
|
||
application like this we would certainly recommend looking into using a sophisticated client-side JavaScript approach.
|
||
|
||
_However_ even in the case of an online spreadsheet there are likely areas where the hypermedia approach might help.
|
||
|
||
The spreadsheet application likely also has a settings page. And perhaps that settings page _is_ amenable to
|
||
the hypermedia approach. If it is simply a set of relatively straight-forward forms that need to be persisted to the
|
||
server, the chances are good that hypermedia would, in fact, work great for this part of the app.
|
||
|
||
And, by adopting hypermedia for that part of your application, you might be able to simplify that part of the application
|
||
quite a bit. You could then save more of your application's _complexity budget_ for the core, complicated spreadsheet logic,
|
||
keeping the simple stuff simple.
|
||
|
||
Why waste all the complexity associated with a heavy JavaScript framework on something as simple as a settings page?
|
||
|
||
.A Complexity Budget
|
||
****
|
||
Any software project has a complexity budget, explicit or not: there is only so much complexity a given development
|
||
team can tolerate and every new feature and implementation choice adds at least a bit more to the overall complexity
|
||
of the system.
|
||
|
||
What is particularly nasty about complexity is that it appears to grow exponentially: one day you can keep the entire
|
||
system in your head and understand the ramifications of a particular change, and a week later the whole system seems
|
||
intractable. Even worse, efforts to help control complexity, such as introducing abstractions or infrastructure to
|
||
manage the complexity, often end up making things even more complex. Truly, the job of the good software engineer
|
||
is to keep complexity under control.
|
||
|
||
The surefire way to keep complexity down is also the hardest: say no. Pushing back on feature requests is an art
|
||
and, if you can learn to do it well, making people feel like _they_ said no, you will go far.
|
||
|
||
Sadly this is not always possible: some features will need to be built. At this point the question becomes: "`what is
|
||
the simplest thing that could possibly work?`" Understanding the possibilities available in the hypermedia approach
|
||
will give you another tool in your "`simplest thing`" tool chest.
|
||
****
|
||
|
||
== Hypermedia: A Sophisticated, Modern System Architecture
|
||
|
||
Hypermedia is often regarded as an old and antiquated technology in web development circles, useful perhaps
|
||
for static websites but certainly not a realistic choice for modern, sophisticated web applications.
|
||
|
||
Seriously? Are we claiming that modern web applications can be built using it?
|
||
|
||
Yes, seriously.
|
||
|
||
Contrary to current popular opinion, hypermedia is an _innovative_ and _modern_ system architecture for building
|
||
applications, in some ways _more modern_ than the prevailing Single Page Application approaches. In the remainder
|
||
of this book we will reintroduce you to the core, practical concepts of hypermedia and then demonstrate exactly how
|
||
you can take advantage of this system architecture in your own software.
|
||
|
||
In the coming chapters you will develop a firm understanding of all the benefits and techniques enabled by this approach.
|
||
We hope that, in addition, you will also become as passionate about it as we are.
|
||
|
||
This book is, in part, a plea that we "`let The Web be The Web`", that we take the original architecture of The Web
|
||
seriously, and that we consider the entire _hypermedia system_ it makes available to us when we build applications
|
||
with it.
|