mkaz.blog

Add React to an Existing Page

I wanted to add React to an existing page, just some Javascript to fancy up the UI. Sadly, there wasn't good documentation on how to do this. There is plenty of documentation on how to use create-react-app to start an entire new application, with built-in web servers, routing, tree shaking, and other things I don't need for just a bit of React.

The React documentation for adding to an existing site shows a dead simple way using script-src tags without JSX, and another way ith more script-src tags to add JSX. Both avoid the build step for simplicity, but it's not all that efficient and I want the build step so I can write typical React code.

React's other documentation recommends using frameworks like Next.js or Gatsby, but those want complete control of the app, routing, and so on. It's great if you want that, not so great if you just want to add a smidge to a single page.

The do-it-yourself recommendation is webpack or Parcel. I do NOT want to mess with webpack config (ever again) and Parcel sounds like the tool I want, but their tutorials likewise take you through setting up an entire app from scratch.

After a bit of digging through Parcel's documentation, here are some quick instructions to add React to an existing app using Parcel. It ends up being rather easy as I hoped.

Starting with an existing HTML page:

public/my-page.html

<!doctype html>
<html>
    <head>
        <title>My Existing Page</title>
    </head>
    <body>
        <p>Stuff.</p>
        <div id="react-stuff-here"></div>
    </body>
</html>

If you haven't used NPM yet in your project, init a package.json and add Parcel and React dependencies.

npm init
npm install --save-dev parcel
npm install --save react react-dom

The real two bits of info you need are configuring what to build and where to put it. This is done in package.json by specifying the source file in the build script:

{
    "scripts": {
        "build": "parcel build src/my-app.js"
    }
}

To specify the target destination, where you want the built file to go, use the targets property:

{
    "targets": {
        "default": {
            "distDir": "./public/js"
        }
    }
}

Create the React app in your source file src/my-app.js

import { createRoot } from "react-dom/client";
 
const MyReactStuff = () => {
    return <div> Do your thing. </div>;
};
 
const container = document.getElementById("react-stuff-here");
const root = createRoot(container);
root.render(<MyReactStuff />);

Run npm run build and it will compile the JS and output it to ./public/js directory.

Add a script tag in your HTML file and it should all come together nicely.

<script defer src="/js/my-app.js"></script>

Parcel has a watch command too if you want some hot reloading during development. Here is a basic package.json with both scripts and a target defined.

{
    "scripts": {
        "dev": "parcel watch src/my-app.js",
        "build": "parcel build src/my-app.js"
    },
    "targets": {
        "default": {
            "distDir": "./public/js"
        }
    },
    "browserslist": "> 2%, last 2 versions, not dead",
    "devDependencies": {
        "parcel": "^2.8.2",
        "process": "^0.11.10"
    },
    "dependencies": {
        "react": "^18.2.0",
        "react-dom": "^18.2.0"
    }
}

That's it, works nice without all the extra overhead.