Enhance browser-JavaScript support to include JSX/Typescript syntax for websites utilizing importmaps.
With all major browsers now supporting importmaps
, bundle-free web development workflows have become both feasible and incredibly convenient. This project seeks to bring that convenience to React/Typescript projects.
Leverages importmaps in conjunction with the ES Module Shim library. With shimMode
forced to true
, all Source Code from the website origin is transpiled using Babel, while prior-optimized imports originating from a module CDN (such as the excellent JSPM CDN) are loaded directly.
Include the esm-x
library (328kB gzipped) as the first script in your HTML file, and include at least one <script type="esm-x">...</script>
. Scripts of type="esm-x"
will be transpiled and executed in the order they are included in the HTML page.
Here is an example of a simple React application with the react
and react-dom
library imports defined via an importmap. Copy this file into index.html
, and serve via a web server (i.e. npx http-server -c-1
). There is an example of an @mui/material
app in the test directory of this repository.
esm-x
works without an importmap, but ES Module Shims is required.
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>ESM-X Example</title>
<!-- Include ESM-X here -->
<script
id="esm-x"
compiler="babel"
loading="circular"
src="https://www.unpkg.com/@zachsa/esm-x@1.0.32/dist/index.js"
></script>
<!-- https://generator.jspm.io/#U2NhYGBiDs0rySzJSU1hKEpNTC7RTcnPdTC00DPSM9BPzslMzSuBiEPFAIy0jtgzAA -->
<script type="importmap">
{
"imports": {
"react": "https://ga.jspm.io/npm:react@18.2.0/index.js",
"react-dom/client": "https://ga.jspm.io/npm:react-dom@18.2.0/client.js"
},
"scopes": {
"https://ga.jspm.io/": {
"react-dom": "https://ga.jspm.io/npm:react-dom@18.2.0/index.js",
"scheduler": "https://ga.jspm.io/npm:scheduler@0.23.0/index.js"
}
}
}
</script>
<!-- ES Module Shims -->
<script
async
src="https://ga.jspm.io/npm:es-module-shims@1.9.0/dist/es-module-shims.js"
crossorigin="anonymous"
></script>
<!-- ESM-X script -->
<script type="esm-x">
import React, { FC } from 'react';
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root') as HTMLElement);
const App: FC = () => <div>Hello from ESM-X</div>;
root.render(<App />);
</script>
</head>
<body>
<div id="root"></div>
</body>
</html>
Configure the ESM-X script by including HTML tag id and other attributes:
<script id="esm-x" loading="circular|linear|disabled" compiler="babel|esbuild" src="..."></script>
Head to the JSPM generator to quickly generate an importmap. Any importmap configuration should be supported - huge importmaps are fine, make sure to take advantage of dynamic imports / code splitting (for example, Suspense/lazy
when using React), etc. (and obviously don't preload scripts)
To use an external importmap, make sure that your importmap tag is of type "importmap-shim", and that the src url endsWith('importmap') || endsWith('importmap.json')
. For example:
<script type="importmap-shim" src="path/to/file/called/importmap.json"></script>
It's easy to work with external importmaps using the jspm CLI
.
Start a local web server and navigate to localhost:3000/test:
npx @mnemosyne/server -v ./
chomp --watch
npm publish --access public