htmelt
Version:
Bundle your HTML assets with Esbuild and LightningCSS. Custom plugins, HMR platform, and more.
99 lines (97 loc) • 2.79 kB
JavaScript
// src/client/devModules.ts
var modules = {};
var missingImports = localStorage.getItem("missingImports")?.split(",") || [];
globalThis.htmelt = {
modules,
import(id) {
const mod = modules[id];
if (!mod) {
if (!missingImports.includes(id)) {
missingImports.push(id);
localStorage.setItem("missingImports", missingImports.join(","));
location.reload();
}
throw Error("Module not found: " + id);
}
if (missingImports.includes(id)) {
missingImports.splice(missingImports.indexOf(id), 1);
localStorage.setItem("missingImports", missingImports.join(","));
}
return mod.exports;
},
export(id, rawExports) {
const mod = modules[id] = { exports: {}, rawExports };
for (const rawExport of rawExports) {
if (Array.isArray(rawExport)) {
const [name, value] = rawExport;
mod.exports[name] = value;
} else if ("from" in rawExport) {
Object.setPrototypeOf(
mod.exports,
new Proxy(Object.getPrototypeOf(mod.exports), {
get(prototype, key) {
const fromModule = modules[rawExport.from];
if (!fromModule) {
throw Error("Module not found: " + rawExport.from);
}
if (rawExport.aliases) {
key = rawExport.aliases[key] ?? key;
}
const value = fromModule.exports[key];
if (value !== void 0) {
return value;
}
return prototype[key];
}
})
);
} else if ("values" in rawExport) {
for (const [name, get] of Object.entries(rawExport.values)) {
Object.defineProperty(mod.exports, name, { get });
}
} else if ("name" in rawExport) {
const { name, get } = rawExport;
Object.defineProperty(mod.exports, name, { get });
}
}
}
};
// src/client/connection.ts
function connect() {
const ws = new WebSocket(import.meta.env.HMR_URL);
ws.onmessage = async ({ data }) => {
const { id, src, args } = JSON.parse(data);
const apply = (await import(src)).default;
const result = await apply(...args);
ws.send(
JSON.stringify({
type: "result",
id,
result
})
);
};
let connected = false;
ws.onopen = () => {
if (!connected) {
console.info("[HMR] connected");
connected = true;
}
};
let reconnecting = false;
const reconnect = () => {
if (!reconnecting) {
reconnecting = true;
setTimeout(connect, 1e3);
}
};
ws.onerror = reconnect;
ws.onclose = () => {
if (connected) {
console.info("[HMR] disconnected");
connected = false;
}
reconnect();
};
}
connect();