OOZOU
Get in Touch
Back to Blog

Building Static Sites without React - Using React (Part 1/3)

React is good and we love using it but we just don't want it inside our compiled HTML, CSS, and Javascript.

July 20, 2020
3 min read
Building Static Sites without React - Using React (Part 1/3)

It's 2020 and people are talking more and more about static site generations with UI frameworks such as React. We have a lot of decent libraries, if not frameworks, such as Gatsby, NextJS, react-static, etc.

So, why do we talk about another method for static site generation instead of using these existing amazing tools?

Well, in the foundation, all those create static HTML, CSS, and Javascript files for you but they include the footprints of React within them. That is not a bad thing at all, in fact, that's the best thing ever happened. You get the runtime of React and the benefit of virtual DOM follows. However, imagine when we are required to create just plain old HTML files with some UI logic implemented in the client-side script. We can use lots of template engines out there, but why not React?

The Overview

Since React introduced renderStaticMarkup, many use it to do server-side rendering for plain HTML and that's neat. We'll use it to generate the pre-rendered content. We'll then extract CSS and related Javascript files. Finally, we put the pre-rendered content into the HTML template with the correct script and stylesheet tags populated and output the files.

The Setup

Let's start off with our package.json file

{
  "name": "react-no-react",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "react": "^16.9.0",
    "react-dom": "^16.9.0"
  },
  "devDependencies": {
    "@babel/cli": "^7.8.4",
    "@babel/core": "^7.10.4",
    "@babel/node": "^7.10.4",
    "@babel/preset-env": "^7.9.5",
    "@babel/preset-react": "^7.9.4",
    "glob": "^7.1.6"
  }
}

As you can see, we need React, ReactDOM, and Babel. Babel is for transpiling the client-side Javascript we might write in ES6. We'll also use babel-node as our CLI tool. Let's create our project structure.

.
├── pages
│   ├── AboutUs.jsx
│   └── Home.jsx
├── scripts
│   └── build.js
├── babel.config.js
└── package.json

In babel.config.js we create our configuration like this

module.exports = {
  presets: ["@babel/env", "@babel/react"],
};

Then, in our scripts/build.js.

import React from "react";
import path from "path";
import fs from "fs";
import glob from "glob";
import { renderToStaticMarkup } from "react-dom/server";
import { spawnSync } from "child_process";

const cwd = path.resolve(__dirname, "..");

// We glob all the files under "pages" directory
const reactFiles = glob.sync("pages/**/*.jsx", { cwd });

reactFiles.forEach((reactFile) => {
  const fileName = path.basename(reactFile).replace(".jsx", "");

  // Page components are from "default" export
  const Component = require(path.resolve(__dirname, "../", reactFile)).default;
  const staticMarkup = renderToStaticMarkup(<Component />);

  // Generate HTML file name from ".jsx" files by replacing the extension with ".html"
  const htmlFile = path.resolve(
    __dirname,
    "../dist/",
    reactFile.replace(".jsx", ".html")
  );

  const dirName = path.dirname(htmlFile);

  // In case we have nested page structure, we need to create directory recursively.
  fs.mkdirSync(dirName, { recursive: true });

  fs.writeFileSync(
    htmlFile,
    `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>${fileName}</title>
</head>
<body>
  ${staticMarkup}
</body>
</html>`,
    "utf8"
  );
});

Let's create our pages

// pages/Home.jsx
import React from "react";

export default () => <h1>Home Page</h1>;
``` ```javascript
// pages/AboutUs.jsx
import React from "react";

export default () => <h1>About Us</h1>;

Finally, create a build script inside package.json

...
"scripts": {
  "build": "babel-node scripts/build.js"
},
...

Run the script

npm run build

or

yarn build

Then you should see two new files.

.
├── dist
│   ├── AboutUs.html
│   └── Home.html
...

But those are just plain HTML. What about CSS, JS, and static assets? That is the topic we'll be discussing in the next part. So if you're interested, stay tuned.Read on: Building Static Sites without React - Using React (Part 2/3)

Related Articles

How Can I Design a Software: A Beginners Guide for Business Owners

How Can I Design a Software: A Beginners Guide for Business Owners

Designing software is an exciting yet complex process that involves creativity, logical thinking, and problem-solving skills.

Read More →
The Future of Edge Computing: What Businesses Need to Know

The Future of Edge Computing: What Businesses Need to Know

The digital landscape is evolving rapidly, and businesses must adapt to keep up with rising demands for speed, efficiency, and real-time processing.

Read More →
The Future of Retail: AI, AR, and Digital Transformation Trends

The Future of Retail: AI, AR, and Digital Transformation Trends

Retail is evolving at an unprecedented pace, driven by AI (Artificial Intelligence), AR (Augmented Reality), and digital transformation technologies, revolutionizing the retail industry. Traditional brick-and-mortar stores are no longer just about selling products—they are becoming smart, interactiv

Read More →

Have a Project in Mind?

Let's discuss how we can help bring your ideas to life with our expertise in web and mobile development.

Start a Conversationhello@oozou.com
OOZOU Logo

Bangkok · Singapore · Hong Kong

X
Facebook
Instagram
LinkedIn

Services

  • Web Development
  • AI & Generative AI Solutions
  • Mobile App Development
  • Data Analytics & Engineering
  • UI/UX Design & Product Design
  • Digital Transformation

Company

  • About Us
  • Careers
  • Blog
  • Whitepapers
  • Case Studies
  • Today I Learned
  • Contact

More

  • Industries
  • Get an Estimate
  • Partner Network
© 2026 OOZOU. All rights reserved.
Privacy PolicyCode of ConductABAC Policy