React Raw Dogged
Technical, Frontendtitle: React Raw Dogged created_at: 2025-07-11T14:52:16.823Z updated_at: 2025-07-11T14:52:16.823Z tldr: React without build tools is_published: 1 star: true category: Technical, Frontend share_type: share
Got a strange dig into how to run a react app without a build tools. React doesn't need a compiler like vue and you can use react directly in the HTML script tag. using the CDN Links from here
Why?
No idea why, i created a new project with the vite tools and did npm install, for some reason i came across the size on disk for that folder and it was 400MB, WTF? There is noting in this project and it took so much space. I just wanted to run it without any build tools. Even if thats possible?
JSX and react
Ok react is a library, underneat it uses JSX, its kind of a tokenizer library to convert plain html with added syntax to pure js. And react just executes this. You can build your own tokenizer with js-tokens library. JSX is a specification of the language spec documents here. Internally build tools convert this JSX to plain javascript, we need something to do this manually, we will be using the babel online tool. Lets get started.
Template
From a plain HTML document,
<!DOCTYPE html>
<html>
<head>
<title>No Build tool react</title>
</head>
<body>
<div id="root">
<!--We will need this for filling the document-->
</div>
<script>
// Our compiled js will be added here!
window.onload = () => {
const root = document.getElementById("root");
};
</script>
<!--JS cdn links-->
<script
crossorigin
src="https://unpkg.com/react@18/umd/react.development.js"
></script>
<script
crossorigin
src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
></script>
</body>
</html>
for the first iteration, we will add a simple hello world component using React createElement
api... this is similar to document.createElement
but from react library. We will see added features on this later...
const HelloWorld = React.createElement("h1", {}, "Hola Mundo!");
const root = document.getElementById("root");
ReactDOM.render(HelloWorld, root);
lets try to do the same thing with jsx. We need to compile this as plain js doesn't understand reurning html tags. and put it in the shell,
const HelloWorld = () => {
return(
<div>
<h1>Hola Mundo!</h1>
</div>
);
};
const root = document.getElementById('root');
ReactDOM.render(<HelloWorld />, root);
Will be using https://babeljs.io/repl. Should compile to pure js. Notice the pure /*#__PURE__*/
tag... that is just a function call. The jsx spec is converted to js. We will be compiling with @babel/plugin-transform-react-jsx
.
const HelloWorld = () => {
return /*#__PURE__*/ React.createElement(
"div",
null,
/*#__PURE__*/ React.createElement("h1", null, "Hola Mundo!"),
);
};
const root = document.getElementById("root");
ReactDOM.render(/*#__PURE__*/ React.createElement(HelloWorld, null), root);
want to see something cool? Api for React.
is similar to document.
. just that we can add arrays of children to the element. or chain call. So if we can achieve the same thing with native apis whats the differenc?
lets dig more.
lets add a button and a counter and a state. For simplicity we will be working with the compiled code from now on...
const HelloWorld = () => {
const [count, setCount] = React.useState(0);
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("button", {
onClick: setCount(c => c + 1)
}, "Hola Mundo! -- ", count, " -- mundo ", count + 1));
//👆 notice the inner text children are split and sent as a array of strings
};
const root = document.getElementById('root');
ReactDOM.render( /*#__PURE__*/React.createElement(HelloWorld, null), root);};
lets create an element each time we click the button.
const HelloWorld = () => {
const [count, setCount] = React.useState(0);
return /*#__PURE__*/ React.createElement(
"div",
null,
/*#__PURE__*/ React.createElement(
"button",
{
onClick: () => setCount((c) => c + 1),
},
"Hola Mundo! -- ",
count,
),
Array(count)
.fill(0)
.map((c) => /*#__PURE__*/ React.createElement("h1", null, count)),
/*#__PURE__*/ React.createElement(
"div",
null,
/*#__PURE__*/ React.createElement("code", null, count), //<- Notice the nesting
),
);
};
for useMemo and useCallbacks, react uses a function call. if you dig deep into the apis, there is a dispatch that is being happening every time a state is being set, and all the children nodes are listening to that dispatch to update.
lets console.log one of these jsx child. You will see a react.element
type object... this is unique for each node... the React.createElement
created this node. and the same is used to update, memoize and render the nodes on the UI
your hello world should look like this.
const HelloWorld = () => {
const [count, setCount] = React.useState(0);
const btn = /*#__PURE__*/ React.createElement(
"button",
{
onClick: () => setCount((c) => c + 1),
},
"Hola Mundo! -- ",
count,
);
console.log(btn);
return btn;
};
you should be able to able to explore the internals from here. Happy exploring
Like it ?
Share with friends