Created
January 20, 2024 09:37
-
-
Save hyrious/8a863ec2d78047af7e4a91689b2b0b3c to your computer and use it in GitHub Desktop.
esbuild # 3604
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<textarea id="code" rows="15" cols="80">import {useState} from 'react' | |
import {Button} from '@mui/material' | |
export default function App() { | |
const [count, setCount] = useState(0) | |
return <> | |
<Button variant="outlined" onClick={() => setCount(c => c + 1)}> | |
Count: {count} | |
</Button> | |
</> | |
} | |
</textarea> | |
<p><button onclick="run()">Run!</button></p> | |
<div id="target" style="border: 1px solid; padding: 1em; white-space: pre;">Press [Run].</div> | |
<script src="https://cdn.jsdelivr.net/npm/react@18.2.0/umd/react.production.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/react-dom@18.2.0/umd/react-dom.production.min.js"></script> | |
<script> | |
// Because 'react' and 'react-dom' should always use the same one, | |
// it is externalized from the server bundle and we inject them here. | |
window.require = (name) => { | |
if (name === 'react') return React | |
if (name === 'react-dom') return ReactDOM | |
throw new Error('Failed to require ' + JSON.stringify(name)) | |
} | |
let root | |
function run() { | |
fetch('http://localhost:3000/build', { | |
method: 'POST', | |
body: document.getElementById('code').value | |
}) | |
.then(async r => { | |
if (r.ok) return r.text() | |
throw new Error(await r.text()) | |
}) | |
.then(bundle => { | |
// bundle is a string like 'var serverBundle = (() => mod)()' | |
const mod = Function(bundle + '\nreturn serverBundle;')() | |
const App = mod && mod.__esModule ? mod.default : mod | |
root && root.unmount() | |
root = ReactDOM.createRoot(document.getElementById('target')) | |
root.render(React.createElement(App)) // root.render(<App />) | |
}) | |
.catch(err => { | |
root && root.unmount() | |
root = null | |
document.getElementById('target').textContent = err + '' | |
}) | |
} | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"dependencies": { | |
"@emotion/react": "^11.11.3", | |
"@emotion/styled": "^11.11.0", | |
"@mui/material": "^5.15.5" | |
}, | |
"devDependencies": { | |
"esbuild": "^0.19.11" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const http = require('node:http') | |
const esbuild = require('esbuild') | |
http.createServer((req, res) => { | |
res.setHeader('Access-Control-Allow-Origin', '*') | |
if (req.method === 'POST' && req.url === '/build') { | |
return (async () => { | |
const chunks = [] | |
for await (const c of req) chunks.push(c) | |
const code = Buffer.concat(chunks).toString('utf8') | |
const { outputFiles } = await esbuild.build({ | |
stdin: { contents: code, loader: 'jsx', resolveDir: '.' }, | |
bundle: true, | |
write: false, | |
globalName: 'serverBundle', | |
external: ['react', 'react-dom'], // will externalize 'react/jsx-runtime' too | |
plugins: [{ | |
name: 'include-react-jsx-runtime', | |
setup({ onResolve }) { | |
onResolve({ filter: /^react\/jsx-runtime$/ }, args => { | |
return { path: require.resolve(args.path) } | |
}) | |
} | |
}] | |
}).catch(err => { | |
res.statusCode = 400 | |
res.end(String(err)) | |
}) | |
if (!outputFiles) return | |
const bundle = outputFiles[0].contents | |
res.end(bundle) | |
})() | |
} | |
res.statusCode = 404 | |
res.end() | |
}) | |
.listen(3000, () => console.log('POST http://localhost:3000/build "code" => "bundle"')) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
npm install
in the package's foldernode serve.js
to start the backend service