Skip to content

Instantly share code, notes, and snippets.

@creationix
Last active April 1, 2020 20:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save creationix/1f298e9a07ad0a1f701e2a9a09de7963 to your computer and use it in GitHub Desktop.
Save creationix/1f298e9a07ad0a1f701e2a9a09de7963 to your computer and use it in GitHub Desktop.
import 'magic-script-polyfills';
import lumin from 'lumin';
import uv from 'uv';
import ssl from 'ssl';
import egl from 'egl';
import gl from 'gl';
import png from 'png';
import jpeg from 'jpeg';
function require(name) {
switch(name) {
case 'lumin': return lumin;
case 'uv': return uv;
case 'ssl': return ssl;
case 'egl': return egl;
case 'gl': return gl;
case 'png': return png;
case 'jpeg': return jpeg;
}
throw new Error(`No such supported builtin module: ${name}`);
}
let url;
try {
url = uv.osGetenv("APP_URL");
} catch (err) {
if (!url) throw new Error("Please set APP_URL variable. For example, use v flag in mldb launch `-v APP_URL=http://192.168.0.50:8000/app.js`")
}
console.log(`Downloading ${url}...`);
fetch(url)
.then(res => {
if (res.status !== 200) throw new Error(`Expected 200 status code, but got ${res.status}`);
return res.text();
})
.then(body => {
console.log(`Evaluating downloaded body ${body.length} as cjs module...`)
const exports = {}
const module = {exports}
eval(`(module, exports, require) => { ${body} }`)(module, exports, require);
})
.catch(err => {
console.log(err.stack)
});
const rollup = require('rollup');
const resolve = require('rollup-plugin-node-resolve');
const commonjs = require('rollup-plugin-commonjs');
var os = require('os');
const http = require('http');
const urlParse = require('url').parse
const pathJoin = require('path').join
const server = http.createServer((req, res) =>
handleRequest(req, res).catch((err) => {
res.statusCode = 500;
res.end(err.stack + "\n")
})
);
server.on('clientError', (err, socket) => {
socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
});
server.listen(8000, "0.0.0.0", () => {
const port = server.address().port
console.log(`Rollup IIFE server listening on the following external interfaces:`)
const ifaces = os.networkInterfaces();
for (const name in ifaces) {
for (const { internal, family, address } of ifaces[name]) {
if (internal || family !== 'IPv4') continue;
console.log(` ${name}:\n http://${address}:${port}/`)
}
}
});
async function handleRequest(req, res) {
const { pathname } = urlParse(req.url);
if (!/\.js$/.test(pathname)) {
res.statusCode = 400;
return res.end("Not a JavaScript module\n");
}
const input = pathJoin(__dirname, "src", pathname)
console.log(`Creating bundle for ${pathname}...`)
const bundle = await rollup.rollup({
input,
external: ['uv', 'lumin', 'egl', 'png', 'gl', 'jpeg', 'ssl'],
plugins: [resolve(), commonjs()],
});
console.log(`Generating bundle for eval...`)
const { output } = await bundle.generate({
format: "cjs",
});
const [{ code }] = output
const body = Buffer.from(code);
console.log(`Sending ${body.length} bytes of JavaScript...`)
res.setHeader('Content-Type', 'application/javascript')
res.end(body);
}
@creationix
Copy link
Author

creationix commented Apr 1, 2020

To use this, first make sure you have the dependencies npm i rollup rollup-plugin-node-resolve rollup-plugin-commonjs and run it with node rollup-serve.js in the root of your project. It serves src/**.js files as single-file CJS module strings that are ready to pass to eval. It resolves both ES6 module imports as well as node.js style requires.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment