🧠 Understanding JavaScript Environments, React SSR, and How the Browser and Server Work Together

Created by eneaslari 11/12/2025

nodejs webdev react bun

Most developers learn JavaScript piece by piece — first in the browser, then frameworks, then something like React or Node, but rarely do they step back and understand the whole ecosystem and how all the parts fit together.

This article walks from the very beginning — what JavaScript really is — to modern concepts like React Server-Side Rendering (SSR), in a clear, logical progression.


1️⃣ What Is JavaScript Really?

JavaScript is a programming language, just like Python, Go, or C#. But unlike many languages, JavaScript was originally designed to run inside the browser to make web pages interactive.

Example (browser JavaScript):

document.querySelector("button").onclick = () => alert("Clicked!");

JavaScript the language does not define:

  • document
  • window
  • DOM manipulation
  • networking
  • file access

Those features come from the browser environment, not from JavaScript itself.


2️⃣ Who Controls JavaScript?

The JavaScript language standard is maintained by:

TC39, part of ECMA International.

It includes representatives from:

  • Google (V8)
  • Apple (JavaScriptCore)
  • Mozilla (SpiderMonkey)
  • Microsoft
  • Meta, Shopify, and others

TC39 defines language features like:

  • async/await
  • optional chaining (?.)
  • classes
  • generators
  • array methods (flat, at, findLast)

Once approved, JavaScript engines implement them.


3️⃣ JavaScript Engines

A JavaScript engine is a program that executes JavaScript code.

Examples:

Engine Used In
V8 Chrome, Node.js, Deno
JavaScriptCore Safari, Bun
SpiderMonkey Firefox

The engine parses, optimizes, and executes code — but it doesn’t provide APIs like fs, window, or fetch. Those come from the runtime.


4️⃣ JavaScript in the Browser

In the browser, JavaScript runs alongside:

  • HTML (structure)
  • CSS (appearance)
  • DOM APIs (interaction)

Example:

<input id="name">

<script>
  document.getElementById("name")
    .addEventListener("input", e => {
      console.log("User typed:", e.target.value);
    });
</script>

Browser JavaScript can:

✔ Update UI ✔ Handle input ✔ Fetch remote data

But cannot:

❌ access the local filesystem ❌ open random network ports ❌ directly access hardware

Browsers intentionally sandbox JavaScript for security.


5️⃣ JavaScript on the Server (Node.js, Bun, Deno)

In 2009, Node.js introduced the idea of running JavaScript outside the browser using Google’s V8 engine.

Example (Node):

import http from "http";

http.createServer((req, res) => {
  res.end("Hello from Node");
}).listen(3000);

Example (Bun):

Bun.serve({
  port: 3000,
  fetch() {
    return new Response("Hello from Bun");
  }
});

Server JavaScript can:

✔ read/write files ✔ process requests ✔ connect to databases ✔ send emails ✔ run scheduled tasks

Here, JavaScript behaves like Python, PHP, or Go.


6️⃣ Browser vs Server: Same Language, Different Powers

Feature Browser Node / Bun
DOM (document) ✔ Yes ❌ No
File system access ❌ No ✔ Yes
Can render UI ✔ Yes ❌ No
Can run a server ❌ No ✔ Yes

The syntax is the same, but the capabilities differ depending on the runtime environment.


7️⃣ How JavaScript Produces a Web Page

Whenever you visit a site, this happens:

Browser → sends request to server
Server → sends HTML, CSS, JS files
Browser → renders HTML and applies CSS
Browser → executes JavaScript

JavaScript may then:

  • fetch more data
  • update the page
  • respond to user actions

8️⃣ What Is React?

React is a JavaScript library created to manage UI and state efficiently.

Before React, updating the DOM manually was complex and error-prone.

React lets developers write UI declaratively:

<button onClick={() => setCount(count + 1)}>
  {count}
</button>

React decides how to update the browser’s DOM intelligently.


9️⃣ JSX Is Not JavaScript

JSX looks like HTML inside JavaScript:

<h1>Hello</h1>

But browsers cannot execute JSX directly. JSX must be compiled into:

React.createElement("h1", null, "Hello");

Without a bundler, we must write the React.createElement version manually.


🔟 React SSR (Server-Side Rendering)

React can run on the server to generate HTML before the browser loads the JavaScript.

Example:

import { renderToString } from "react-dom/server";
renderToString(<App />);

This produces:

<h1>Hello</h1>

Benefits:

  • Faster first render
  • SEO-friendly output
  • Better perceived performance

1️⃣1️⃣ Hydration: Making Server-Rendered HTML Interactive

Once the browser receives HTML, React JavaScript loads and hydrates it:

ReactDOM.hydrate(<App />, document.getElementById("root"));

Hydration attaches event listeners and turns the static HTML into a fully interactive React app.

For hydration to work, the server and browser must generate the same markup.


1️⃣2️⃣ Why Sometimes We Don’t Import React

If React is loaded via a CDN script tag:

<script src="https://unpkg.com/react@18/umd/react.development.js"></script>

React becomes a global variable (window.React), so imports aren’t necessary.

With ES modules and bundlers, we must import React explicitly:

import React from "react";

🔥 Practical Examples

Below are three runnable examples showing how rendering works differently depending on the environment.


Example 1 — Browser-Only Rendering (CSR)

<div id="root"></div>

<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>

<script>
  function App() {
    return React.createElement("h1", null, "Rendered in Browser");
  }

  ReactDOM.createRoot(document.getElementById("root"))
    .render(React.createElement(App));
</script>

The browser receives empty HTML and React builds the UI.


Example 2 — SSR with Node.js

server.js

import express from "express";
import React from "react";
import ReactDOMServer from "react-dom/server";

function App({ name }) {
  return React.createElement("h1", null, `Hello, ${name}`);
}

const app = express();
app.use(express.static("public"));

app.get("/", (req, res) => {
  const html = ReactDOMServer.renderToString(React.createElement(App, { name: "Node.js" }));

  res.send(`
    <html>
      <body>
        <div id="root">${html}</div>
        <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
        <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
        <script src="/client.js"></script>
      </body>
    </html>
  `);
});

app.listen(3000);

public/client.js

function App({ name }) {
  return React.createElement("h1", null, `Hello, ${name}`);
}

ReactDOM.hydrate(
  React.createElement(App, { name: "Node.js" }),
  document.getElementById("root")
);

Example 3 — SSR with Bun

server.js

import React from "react";
import ReactDOMServer from "react-dom/server";

function App({ name }) {
  return React.createElement("h1", null, `Hello, ${name}`);
}

Bun.serve({
  port: 3000,
  fetch(req) {
    if (new URL(req.url).pathname === "/client.js") {
      return new Response(Bun.file("public/client.js"));
    }

    const html = ReactDOMServer.renderToString(React.createElement(App, { name: "Bun" }));

    return new Response(`
      <html>
        <body>
          <div id="root">${html}</div>
          <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
          <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
          <script src="/client.js"></script>
        </body>
      </html>
    `, { headers: { "Content-Type": "text/html" } });
  }
});

console.log("SSR App running at http://localhost:3000");

public/client.js

function App({ name }) {
  return React.createElement("h1", null, `Hello, ${name}`);
}

ReactDOM.hydrate(
  React.createElement(App, { name: "Bun" }),
  document.getElementById("root")
);

More to read


🧠 Understanding JavaScript Environments, React SSR, and How the Browser and Server Work Together
11/12/2025

Most developers learn JavaScript piece by piece — first in the browser, then frameworks, then something like React or Node, but rarely do they step back and understand the **whole ecosystem** and how all the parts fit together.

🚀 How I Accidentally Summoned Git Demons (and Eventually Learned How to Clone My Repo the Right Way)
14/11/2025

A fun, step-by-step story of how I cloned my existing website repo to create a modified version without touching the original—while accidentally adding the wrong origin, dealing with “main vs master,” triggering GitHub’s secret-scanning police, and ultimately learning how to properly duplicate a repo, clean commits, remove secrets, and push safely. A lighthearted guide for anyone who wants to use an existing project as a template without the Git chaos.

🐳 The Complete Guide to Dockerizing a Node.js + Express App with Database & File Uploads
13/8/2025

This guide explains how to build, run, and persist a Node.js + Express application inside Docker — with support for MongoDB, PostgreSQL, and file uploads — and also clarifies the relationship between images, containers, and volumes.

My New Plan: Making a Mini-Game Every Week
21/2/2025

This week, I realized that working on big projects can sometimes feel slow, and it’s easy to lose motivation. So, I came up with a new plan—I’ll create and release a small game every week!