mirror of
https://github.com/bigskysoftware/hypermedia-systems.git
synced 2025-12-04 00:05:18 -05:00
Merge branch 'main' of github.com:bigskysoftware/building-hypermedia-systems
This commit is contained in:
commit
c3ce0e2d1a
@ -599,7 +599,7 @@ software. While there are still times and places for the more complex SPA appro
|
||||
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 htmx (https://htmx.org). Htmx will be the focus of Part Two.
|
||||
One such hypermedia oriented library is https://htmx.org[htmx]. Htmx will be the focus of Part Two.
|
||||
We show that you can, in fact, create many common "`modern`" UI features found in sophisticated Single
|
||||
Page Applications by instead using the hypermedia model.
|
||||
|
||||
|
||||
@ -3,18 +3,17 @@
|
||||
:chapter: 02
|
||||
:url: ./hypermedia-components/
|
||||
|
||||
A _hypermedia system_ consists of a number of components that come together to make the entire distributed system work,
|
||||
including:
|
||||
A _hypermedia system_ consists of a number of components:
|
||||
|
||||
* A hypermedia, such as HTML
|
||||
* A network protocol, such as HTTP
|
||||
* A server that presents a hypermedia API, that is, that responds to network requests with hypermedia responses
|
||||
* A server that presents a hypermedia API responding to network requests with hypermedia responses
|
||||
* A client that properly interprets those responses
|
||||
|
||||
In this chapter we will look at these components and their implementation in the context of the web.
|
||||
|
||||
Once we have reviewed the major components of the web as a hypermedia system, we will look at Chapter 5 of Roy
|
||||
Fielding's dissertation, "`Architectural Styles and the Design of Network-based Software Architectures.`" This is where the
|
||||
Once we have reviewed the major components of the web as a hypermedia system, we will look at key insights developed by Roy
|
||||
Fielding in his dissertation, "`Architectural Styles and the Design of Network-based Software Architectures.`" We will see where the
|
||||
terms REpresenation State Transfer (REST), RESTful and Hypermedia As The Engine Of Application State (HATEOAS) come from,
|
||||
and we will analyze these terms in the context of the web.
|
||||
|
||||
@ -26,11 +25,11 @@ term REST is currently used in the industry -- are not.
|
||||
|
||||
=== The Hypermedia
|
||||
|
||||
The fundamental technology of a hypermedia system is a particular hypermedia or multiple hypermedia that allow a
|
||||
The fundamental technology of a hypermedia system is a hypermedia that allows a
|
||||
client and server to communicate with one another in a dynamic, non-linear fashion. Again, what makes a hypermedia
|
||||
a hypermedia is the presence of _hypermedia controls_, that is, elements in the hypermedia that allow users to select
|
||||
non-linear actions within the hypermedia. That is to say, the user can _interact_ with the media in a manner beyond
|
||||
simply reading it from start to end.
|
||||
a hypermedia is the presence of _hypermedia controls_: elements in the hypermedia that allow users to select
|
||||
non-linear actions within the hypermedia. Users of a hypermedia system can _interact_ with the media in a manner beyond
|
||||
simply reading from start to end.
|
||||
|
||||
We have already mentioned the two primary hypermedia controls in HTML, anchors and forms, which allow a browser to
|
||||
present links and operations to a user through a browser.
|
||||
@ -310,8 +309,8 @@ pattern in htmx-powered applications is to use a custom header set by htmx, `HX-
|
||||
"`normal`" web requests and requests submitted by htmx. To properly cache the response to these requests, the `HX-Request`
|
||||
request header must be indicated by the `Vary` response header.
|
||||
|
||||
A full discussion of caching HTTP responses is beyond the scope of this chapter, but please see
|
||||
https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching[The MDN Article on HTTP Caching] for a more in-depth discussion.
|
||||
A full discussion of caching HTTP responses is beyond the scope of this chapter; see
|
||||
the https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching[MDN Article on HTTP Caching] if you would like to know more on the topic.
|
||||
|
||||
=== Hypermedia Servers
|
||||
|
||||
@ -543,7 +542,7 @@ in the form of hypermedia controls.
|
||||
|
||||
This might sound a little abstract, lets look at a concrete example.
|
||||
|
||||
Consider two different potential responses from of an HTTP server for the URL `https://example.com/contacts/42`.
|
||||
Consider two different potential responses from of an HTTP server for the URL `https://example.com/contacts/42`.
|
||||
|
||||
Both responses will return information about a contact, but they will take very different forms.
|
||||
|
||||
@ -758,8 +757,7 @@ operations and resources in it, and display it to users to work with.
|
||||
|
||||
=== Layered System
|
||||
|
||||
The final "`required`" constraint on a RESTful system that we will consider is The Layered System constraint. This constraint can be found in
|
||||
https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_6[Section 5.1.6] of Fielding's dissertation.
|
||||
The final "`required`" constraint on a RESTful system that we will consider is The Layered System constraint. This constraint can be found in https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_6[Section 5.1.6] of Fielding's dissertation.
|
||||
|
||||
To be frank, after the excitement of the uniform interface constraint, the "`layered system`" constraint is a bit of a
|
||||
let down. But it is still worth understanding and it is actually utilized effectively by The web. The constraint
|
||||
|
||||
@ -45,7 +45,7 @@ update existing content, entirely outside the normal browser request mechanism.
|
||||
****
|
||||
|
||||
There are a few different styles of SPA, but, as we discussed in Chapter 1, the most common approach today is to tie
|
||||
the DOM to a JavaScript model and then let an SPA framework like react (https://reactjs.org/) or vue (https://vuejs.org/)
|
||||
the DOM to a JavaScript model and then let an SPA framework like https://reactjs.org/[React] or https://vuejs.org/[Vue]
|
||||
_reactively_ update the DOM when a JavaScript model is updated: you make a change to a JavaScript object that is
|
||||
stored locally in memory in the browser, and the web page "`magically`" updates its state to reflect the change in the
|
||||
model.
|
||||
@ -80,10 +80,10 @@ this book:
|
||||
|
||||
Let's break down in painstaking detail exactly what happens with this link:
|
||||
|
||||
* The browser will render the text "`Hypermedia Systems`" to the screen, likely with a decoration indicating it is clickable
|
||||
* The browser will render the text "`Hypermedia Systems`" to the screen, likely with a decoration indicating it is clickable.
|
||||
* Then, when a user clicks on the text...
|
||||
* The browser will issue an HTTP `GET` to `https://hypermedia.systems` and then...
|
||||
* The browser will load the HTML body of the HTTP response into the browser window, replacing the current document
|
||||
* The browser will issue an HTTP `GET` to `https://hypermedia.systems`...
|
||||
* The browser will load the HTML body of the HTTP response into the browser window, replacing the current document.
|
||||
|
||||
So we have four aspects of a simple hypermedia link like this, with the last three aspects supplying the mechanism that distinguishes
|
||||
a hyperlink from "`normal`" text and makes this a hypermedia control.
|
||||
@ -193,7 +193,7 @@ its pursuit of extending HTML as a hypermedia.
|
||||
|
||||
=== Installing and Using htmx
|
||||
|
||||
From a practical "`getting started`" perspective, htmx is a simple, dependency-free and stand-alone JavaScript library that
|
||||
From a practical "`getting started`" perspective, Htmx is a simple, dependency-free and stand-alone JavaScript library that
|
||||
can be added to a web application by simply including it via a `script` tag in your `head` element.
|
||||
|
||||
Because of this simple installation model, you can take advantage of tools like public CDNs to install the library.
|
||||
|
||||
@ -151,7 +151,7 @@ place it on a parent, the attribute will also apply to children elements. This
|
||||
that idea inspired htmx to adopt a similar "`cascading htmx attributes`" feature.
|
||||
|
||||
To avoid the redundancy in this example, let's introduce a `div` element that encloses all the links and then "`hoist`" the
|
||||
`hx-boost` attribute up to that parent `div`. This will let us remove the redundant `hx-boost` attributes but ensure all the links are
|
||||
`hx-boost` attribute up to that parent `div`. This will let us remove the redundant `hx-boost` attributes but ensure all the links are
|
||||
still boosted, inheriting that functionality from the parent `div`.
|
||||
|
||||
Note that any legal HTML element could be used here, we just use a `div` out of habit.
|
||||
@ -472,7 +472,7 @@ button, the application would just delete that contact. Too bad, so sad for the
|
||||
Fortunately htmx has an easy mechanism for adding a confirmation message on destructive operations like this: the
|
||||
`hx-confirm` attribute. You can place this attribute on an element, with a message as its value, and the JavaScript
|
||||
method `confirm()` will be called before a request is issued, which will show a simple confirmation dialog to the user
|
||||
asking them to confirm the action. Very easy and a great way to prevent accidents.
|
||||
asking them to confirm the action. Very easy and a great way to prevent accidents.
|
||||
|
||||
Here is how we would add confirmation of the contact delete operation:
|
||||
|
||||
|
||||
@ -413,8 +413,8 @@ a _non-htmx_ request (e.g. refreshing a page) and yet the _htmx_ content is retu
|
||||
in a partial page of content for the user.
|
||||
|
||||
The solution to this problem is to use the HTTP Response `Vary` header and call out the htmx headers that you are using
|
||||
to determine what content you are returning. A full explanation of HTTP Caching is beyond the scope of this book, but
|
||||
https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching[the MDN article] on the topic is quite good, and the https://htmx.org/docs/#caching[htmx
|
||||
to determine what content you are returning. A full explanation of HTTP Caching is beyond the scope of this book, but the
|
||||
https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching[MDN article on the topic] is quite good, and the https://htmx.org/docs/#caching[htmx
|
||||
documentation] discusses this issue as well.
|
||||
****
|
||||
|
||||
|
||||
@ -606,13 +606,13 @@ We can add this functionality quite easily to our application with just a bit of
|
||||
in a Hypermedia-Driven Application in more depth in a few chapters, but as a quick introduction: scripting is perfectly
|
||||
acceptable in an HDA, as long as it doesn't replace the core hypermedia mechanics of the application.
|
||||
|
||||
For our auto-download feature we will use https://hyperscript.org[hyperscript], our preferred scripting option, but the
|
||||
For our auto-download feature we will use https://hyperscript.org[+_hyperscript+] , our preferred scripting option, but the
|
||||
equivalent JavaScript would be nearly as simple.
|
||||
|
||||
All we need to do to implement the auto-download feature is the following: when the download link renders,
|
||||
automatically click on the link for the user.
|
||||
|
||||
The +_hyperscript+ reads nearly identical that sentence (which is why we love hyperscript):
|
||||
The +_hyperscript+ code reads almost the same as the previous sentence (which is why we love hyperscript):
|
||||
|
||||
.Auto-Downloading
|
||||
[source, html]
|
||||
|
||||
@ -86,7 +86,7 @@ when the request had completed, we would write the following HTML:
|
||||
----
|
||||
<1> This tells htmx to show the top of the body after the swap occurs
|
||||
|
||||
More details and examples can be found online at the https://htmx.org/attributes/hx-swap/[documentation page] for `hx-swap`.
|
||||
More details and examples can be found online in the `hx-swap` https://htmx.org/attributes/hx-swap/[documentation].
|
||||
|
||||
=== `hx-trigger`
|
||||
|
||||
@ -192,17 +192,16 @@ regular DOM API. We have already seen `load` and `revealed` in our lazy loading
|
||||
htmx also gives you an `intersect` event that triggers when an element intersects its parent element.
|
||||
|
||||
This synthetic event uses the modern Intersection Observer API, which you can read more about
|
||||
here: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
|
||||
at https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API[MDN].
|
||||
|
||||
Intersection gives you much finer grained control over exactly when a request should be triggered. For example, you can
|
||||
specify a threshold and specify that the request should only be issued when an element is 50% visible.
|
||||
Intersection gives you fine grained control over exactly when a request should be triggered. For example, you can
|
||||
set a threshold and specify that the request be issued only when an element is 50% visible.
|
||||
|
||||
The `hx-trigger` attribute certainly is the most complex one in htmx, and more details and examples can be found on its
|
||||
documentation page: https://htmx.org/attributes/hx-trigger/
|
||||
The `hx-trigger` attribute certainly is the most complex in htmx. More details and examples can be found in its https://htmx.org/attributes/hx-trigger/[documentation].
|
||||
|
||||
=== Other Attributes
|
||||
|
||||
htmx offers many other less commonly used attributes for fine-tuning the behavior of your Hypermedia Driven Application.
|
||||
Htmx offers many other less commonly used attributes for fine-tuning the behavior of your Hypermedia Driven Application.
|
||||
|
||||
Here are some of the most useful ones:
|
||||
|
||||
@ -458,7 +457,7 @@ HTTP responses:
|
||||
`HX-Retarget`::
|
||||
Allows you to specify a new target to swap the response content into on the client side
|
||||
|
||||
You can find a reference for all requests and response headers https://htmx.org/reference/#headers[here].
|
||||
You can find a reference for all requests and response headers in the https://htmx.org/reference/#headers[htmx documentation].
|
||||
|
||||
=== HTTP Response Codes
|
||||
|
||||
@ -492,7 +491,7 @@ document.body.addEventListener('htmx:beforeSwap', function(evt) { <1>
|
||||
|
||||
You can also use the `htmx:beforeSwap` event to configure if the response should be swapped into the DOM and what element
|
||||
the response should target. This gives you quite a bit of flexibility in choosing how you want to use HTTP Response
|
||||
codes in your application. Full documentation on the `htmx:beforeSwap` event can be found https://htmx.org/events/#htmx:beforeSwap[here].
|
||||
codes in your application. Full documentation on the `htmx:beforeSwap` event can be found at https://htmx.org/events/#htmx:beforeSwap[htmx.org].
|
||||
|
||||
== Updating Other Content
|
||||
|
||||
@ -565,7 +564,7 @@ Pull Contacts From Integration <1>
|
||||
<2> this content will be removed from the response and swapped by id
|
||||
|
||||
Using this technique, you are able to piggyback content updates of other elements on top of requests by other elements.
|
||||
The `hx-swap-oob` attribute supports other additional features, all of which are documented https://htmx.org/attributes/hx-swap-oob/[here].
|
||||
The `hx-swap-oob` attribute supports other additional features, all of which are https://htmx.org/attributes/hx-swap-oob/[documented].
|
||||
|
||||
Depending on how exactly your server-side templating technology works, and what level of interactivity your application
|
||||
requires, out of band swapping can be a powerful mechanism for more flexible content updates.
|
||||
@ -718,13 +717,13 @@ on an element, all htmx attributes within that element will be ignored.
|
||||
|
||||
A Content Security Policy (CSP) is a browser technology that allows you to detect and prevent certain types of
|
||||
content injection-based attacks. A full discussion of CSPs is beyond the scope of this book, but we refer you to
|
||||
the https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP[Mozilla Developer Network article] on them for more information.
|
||||
the https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP[Mozilla Developer Network article] on the topic for more information.
|
||||
|
||||
A common feature to disable using a CSP is the `eval()` feature of JavaScript, which allows you to evaluate arbitrary
|
||||
JavaScript code from a string. This has proven to be a security issue and many teams have decided that it is not worth
|
||||
the risk to keep it enabled in their web applications.
|
||||
|
||||
htmx does not make heavy use of `eval()` and, thus, a CSP with this restriction in place will be fine. The one
|
||||
Htmx does not make heavy use of `eval()` and, thus, a CSP with this restriction in place will be fine. The one
|
||||
feature that does rely on `eval()` is event filters, discussed above. If you decide to disable `eval()` for your
|
||||
web application, you will not be able to use the event filtering syntax.
|
||||
|
||||
@ -738,7 +737,7 @@ There are a large number of configuration options available for htmx. Some exam
|
||||
|
||||
A full list of configuration options can be found in the config section of the https://htmx.org/docs/#config[main htmx documentation].
|
||||
|
||||
htmx is typically configured via a `meta` tag, found in the header of a page. The name of the meta tag should be
|
||||
Htmx is typically configured via a `meta` tag, found in the header of a page. The name of the meta tag should be
|
||||
`htmx-config`, and the content attribute should contain the configuration overrides, formatted as JSON. Here is
|
||||
an example:
|
||||
|
||||
|
||||
@ -950,9 +950,9 @@ visual clutter and the toolbar can be extended with more options without creatin
|
||||
|
||||
== _hyperscript
|
||||
|
||||
The final scripting technology we are going to look at is a bit further afield: +_hyperscript+ (https://hyperscript.org[])
|
||||
The final scripting technology we are going to look at is a bit further afield: https://hyperscript.org[+_hyperscript+].
|
||||
|
||||
While the previous two examples are JavaScript-oriented, +_hyperscript+ is an _entire new_ scripting language for front-end
|
||||
While the previous two examples are JavaScript-oriented, +_hyperscript+ is an _entirely new_ scripting language for front-end
|
||||
development. +_hyperscript+ has a completely different syntax than JavaScript, based on an older language called HyperTalk.
|
||||
HyperTalk was the scripting language for a technology called HyperCard, an old hypermedia system available on early
|
||||
Macintosh Computers.
|
||||
@ -960,7 +960,7 @@ Macintosh Computers.
|
||||
The most noticeable thing about +_hyperscript+ is that it resembles English prose more than it resembles other programming
|
||||
languages. +_hyperscript+ was initially created as a sibling project to htmx, because we felt that JavaScript wasn't
|
||||
event-oriented enough, which made adding small scripting enhancements to htmx applications cumbersome. Like Alpine,
|
||||
+_hyperscript+, is a modern jQuery replacement.
|
||||
+_hyperscript+ is a modern jQuery replacement.
|
||||
|
||||
Also like Alpine, +_hyperscript+ allows you to write your scripting inline, in HTML.
|
||||
|
||||
@ -1148,7 +1148,7 @@ to enhance your Hypermedia Driven Application. However, there is another major
|
||||
side scripting: "`off the shelf`" components. That is, JavaScript libraries that other people have created that offer
|
||||
some sort of functionality, such as showing modal dialogs.
|
||||
|
||||
Components have become very popular in the web development works, with libraries like DataTables (https://datatables.net/)
|
||||
Components have become very popular in the web development works, with libraries like https://datatables.net/[DataTables]
|
||||
providing rich user experiences with very little JavaScript code on the part of a user. Unfortunately, if these libraries
|
||||
aren't integrated well into a website, they can begin to make an application feel "`patched together`". Furthermore, some
|
||||
libraries go beyond simple DOM manipulation, and require that you integrate with a server end point, almost invariably
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user