A UI in context of web applications is the HTML, CSS and JS that is sent to the browser.

HTML is the structure of the page. CSS is the styling. JS is for programming browser to manipulate DOM / browser environment.

The rendering patterns are classified based on where are we running the process to generate the html required to display for the user.

Things to keep in mind when rendering

When rendering UI, there are primarily two factors to consider.

  1. State Management : Where is the application state stored and how is it managed.
  2. Interactivity : How the UI is updated for user interaction and state update.

Client Side Rendering

In client side rendering, the javascript sent to the browser is responsible for majority of the rendering the UI. The server typically sends a minimal placeholder where the javascript can replace the content.

example:

<html>
  <head>
    <title>Client Side Rendering</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="client.js"></script>
  </body>
</html>

And the client.js will be responsible for rendering the UI. It will have funcitons and logic to render the UI.

example:

const root = document.getElementById("root");
root.innerHTML = "<h1>Hello World</h1>";

usually

  • we use a framework like react to send http request to get data from server in the form of JSON,
  • with the response we store it in a state value / object
  • it is then used alongside a sort of template ( available in js bundle itself ) to generate html and replace the content in the ui.
sequenceDiagram
    participant B as Browser
    participant S as Server
    participant C as CDN
    B->>+S: GET /route
    S->>-B: index.html
    Note left of B: Page Not Ready
    C-->>+B: script.js
    B->>S: (script.js) GET /data
    S->>B: { "data": ... }
    B->>-B: Update State and Render
    Note left of B: Page is Ready
    B->>+S: (script.js) POST /update
    S->>-B: { "data": ... }
    activate B
    B-->>B: Update State and Render
    deactivate B

In frameworks like react, we send functions that return html as a string and the framework will replace the content in the ui.

example react code:

const Header = () => (
  <div>Header</div>
)

const Footer = () => (
  <div>Footer</div>
)

const Page = () => (
  <>
    <Header/>
    <div>main content </div>
    <Footer/>
  </>
)

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Page/>);

will be transpiled to something like

import { jsx as _jsx } from "react/jsx-runtime";
import { Fragment as _Fragment } from "react/jsx-runtime";
import { jsxs as _jsxs } from "react/jsx-runtime";
const Header = () => /*#__PURE__*/_jsx("div", {
  children: "Header"
});
const Footer = () => /*#__PURE__*/_jsx("div", {
  children: "Footer"
});
const Page = () => /*#__PURE__*/_jsxs(_Fragment, {
  children: [/*#__PURE__*/_jsx(Header, {}), /*#__PURE__*/_jsx("div", {
    children: "main content "
  }), /*#__PURE__*/_jsx(Footer, {})]
});
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render( /*#__PURE__*/_jsx(Page, {}));

and this will be executed in the client to produce html in the browser during the runtime.

whew, that’s a lot of work

State Management

State management in CSR typically involves

  • Local copy of the application state will be stored in the browser itself.
  • Fetching data from server via API calls as JSON
  • Some State management library like Redux, Zustand, Jotai, React Context etc…
  • The UI components itself will have to be aware of the state and render or rerender based on the state.

Interactivity

Javascript is essential for progressively enhanced interactivity.

Interactivity in CSR typically involves

  • The UI components will have to be aware of the state and render or rerender based on the state.
  • User actions update the browser state and then needs a sync with server state.

During CSR the responsibility of the browser is to sync the state with server and replace the DOM with the rendering logic in the script. Any Interaction with state is handled by the script to update the local state and rerender the UI, the updated state can be synced with server via API Calls.

CSR offers high interactivity.

Server Side Rendering

In server side rendering, the server is responsible for rendering the UI. The HTML sent by the server will contain all the information required in the HTML itself. The browser will just render the HTML recieved and the page is ready.

example:

<html>
  <head>
    <title>Server Side Rendering</title>
  </head>
  <body>
    <h1>Hello World</h1>
  </body>
</html>

When using this pattern, the state stays in the server itself, and the server will render the UI based on the state. The browser will just render the HTML recieved.

sequenceDiagram
    participant B as Browser
    participant S as Server
    participant C as CDN
    B->>+S: GET /route
    S->>-B: index.html
    C-->>B: script.js
    Note left of B: Page is ready
    B->>+S: (script.js) POST /update
    S-->>S: State update
    S->>-B: | 
data
| html B->>B: Replace Section Note left of B: Page is Ready

Any changes in state will require a new request to the server and the server will send the new HTML. The browser will have to re render the page or replace the HTML Parts ( depends on the implementation ).

State Management

State management in SSR typically involves

  • The state will be stored in the server itself.
  • The server render the UI attaching the relevant values from the state.
  • Any state change will require a new request to server and the server will respond with new HTML to show the updated state.

Interactivity

Javascript is essential for progressively enhanced interactivity.

Interactivity in SSR typically involves

  • User actions requires a request to server and the server will respond with new HTML to show the updated state.
  • This HTML can be a full page or just a part of the page that needs to be updated.

During SSR the responsibility of the browser is to just render the HTML recieved from server. Any Interaction with the state will have to go through the erver, but the state will be in sync with server.

SSR offers fast initial load times and security.

SSR offers non-enhanced interactivity It’s 2024 and we have tools to achieve enhanced interactivity well. See HTMX to see how.