Skip to content

Instantly share code, notes, and snippets.

@mfdj
Last active February 8, 2026 20:48
Show Gist options
  • Select an option

  • Save mfdj/3616370815c49fe971970e6cdb79f7a3 to your computer and use it in GitHub Desktop.

Select an option

Save mfdj/3616370815c49fe971970e6cdb79f7a3 to your computer and use it in GitHub Desktop.

Goal

Using React JSX directly in native web platform source files (html, js) bypassing the need to build/compile.

Key references

https://peterkellner.net/2024/05/10/running-react-19-from-a-cdn-and-using-esm.sh/

  • got me going in a good direction but didn't have a JSX solution

https://blog.tripu.info/react-19/

  • unlocked the React 19 JSX puzzle trying to juggle ESM and Babel

Noteworthy but not the approach I wanted

Compiling TypeScript/TSX at the edge is interesting but is pure overhead for my use case

import { party } from "./party.js";
export function Message({ greeting, subject }) {
return <div className="message">{party(greeting, subject)}</div>;
}
export function party(...messages) {
return messages
.map((message) => `🎉 ${message}`)
.reduce((agg, next) => `${agg} ${next}`);
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>React 18 no build (UMD)</title>
<script src="https://unpkg.com/react@18.3.1/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone@7.12.4/babel.js"></script>
</head>
<body>
<div id="react-root"></div>
<script type="text/babel">
async function main() {
const { party } = await import("./party.js");
// Attempting to import this component as JSX fails with `Unhandled Promise Rejection: TypeError: 'text/jsx' is not a valid JavaScript MIME type.`
// const { Message } = await import("./components.jsx");
function Message({ greeting, subject }) {
return <div className="message">{party(greeting, subject)}</div>;
}
const element = (
<div className="container">
<Message greeting="Hello" subject="World" />
<Message greeting="Goodbye" subject="World" />
</div>
);
ReactDOM.createRoot(document.getElementById("react-root")).render(
element,
);
}
main();
</script>
</body>
</html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>React 19 no build (ESM, with hacks)</title>
<script type="importmap">
{
"imports": {
"react": "https://esm.sh/react@19.2.0",
"react-dom/client": "https://esm.sh/react-dom@19.2.0/client"
}
}
</script>
<script src="https://unpkg.com/@babel/standalone@7.12.4/babel.js"></script>
</head>
<body>
<div id="react-root"></div>
<script type="module">
import React from "react";
import ReactDOM from "react-dom/client";
window.module_exports = { React, ReactDOM };
</script>
<script type="text/babel">
const { React, ReactDOM } = window.module_exports;
async function main() {
const { party } = await import("./party.js");
// Attempting to import this component as JSX fails with `Unhandled Promise Rejection: TypeError: 'text/jsx' is not a valid JavaScript MIME type.`
// const { Message } = await import("./components.jsx");
function Message({ greeting, subject }) {
return <div className="message">{party(greeting, subject)}</div>;
}
const element = (
<div className="container">
<Message greeting="Hello" subject="World" />
<Message greeting="Goodbye" subject="World" />
</div>
);
ReactDOM.createRoot(document.getElementById("react-root")).render(element);
}
main();
</script>
</body>
</html>
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
port=${1-3000}
php -S "localhost:$port" -t .
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment