An APIs series

Client-Side Communication

Every client-side application eventually talks to something. This series is about your half of that conversation: the half you write, the half you can get wrong, and the half a framework will happily hide from you until the day it matters.

The thesis

There is no such thing as a purely client-side web app. At the very least, it was delivered by a server, and most of the time it also authenticates, saves, and loads through one. Communication is not an advanced topic to bolt on at the end of the syllabus. It is what makes an application a web application rather than a local program built out of web technologies.

This series follows the history because the history is the difficulty curve. It starts with a plain <form>, which already knows how to talk to a server and asks nothing of you. Then it adds one capability at a time: the postback, Ajax, XHR, fetch. At every step you can see what the new tool bought you, and what it now expects you to manage yourself.

You write the client half

Every endpoint used in this series already exists. You will never write one. That is deliberate: the judgment this series teaches is client-side judgment, not server design. It covers four things. What your code does when a request fails and no good answer is coming. What is actually worth putting on the wire, in size and in sensitivity. Whether a response that arrived with a 200 status can be trusted as far as its body. And what client-side validation is for, given that none of it is a security boundary.

How the demos work

One feature runs through all nine steps: a small list of posts, with a form to add to it. Each step ships its own snapshot, so you can diff any two versions and see what changed to get from one to the next, rather than squinting at nine unrelated examples.

Every demo embeds <http-waterfall capture="true">, which patches fetch and XMLHttpRequest in that frame before the demo's own script runs. The traffic you see is the demo's own, produced by the code on the page in front of you, not a recording of someone else's run.

The nine steps

  1. 01The form already talks

    A <form> with no JavaScript at all: field serialization, a GET query string versus a POST body, and action/method as the contract. Plus the truth about client-side validation: required, pattern, and type are UX, not a security boundary.

  2. 02The postback problem

    The full-page round trip, and what it throws away on every submit: scroll position, focus, in-progress state, bandwidth. Ends on the question the rest of the series answers: can we do the communication ourselves?

  3. 03Ajax appears

    The name, the shift, and Hello Ajax World walked step by step. Plus the complexity critique: owning the request yourself means owning state, history, and routing too.

  4. 04XHR up close — coming

    open/send, readyState, status, headers, abort, and timeouts. Why it still matters: it is in code you will meet, and it still reports upload progress, which fetch has no portable equivalent for.

  5. 05fetch, and what changed — coming

    Promises, Request and Response, and AbortSignal.timeout. The fact that trips everyone up: fetch does not reject on 404 or 500. The server answered, so that is data.

  6. 06What to send — coming

    URL-encoded bodies versus FormData versus JSON, multipart for files, and Content-Type as the server's parsing instruction. What is actually worth transmitting, plus a short passage on text encoding.

  7. 07When it goes wrong — coming

    Timeouts, retries, ordering and races, and a 200 carrying garbage. A response is untrusted input: textContent versus innerHTML, and why you never blindly retry a POST.

  8. 08Other people's data — coming

    CORS as client code experiences it: an opaque failure with no status, what triggers a preflight, and the same-origin proxy workaround. Screen scraping and mashups: the fragility and the ethics of depending on data nobody promised you.

  9. 09Beyond request and response — coming

    One-way out with sendBeacon and keepalive, one-way in with server-sent events, and two-way with WebSocket. Plus the caution against reaching for it just because it looks more capable.