feat: Add live-reload

This commit is contained in:
Sidharth Vinod 2023-08-13 18:51:02 +05:30
parent 350aaf9b51
commit 5e210753b7
No known key found for this signature in database
GPG Key ID: FB5CCD378D3907CD
4 changed files with 105 additions and 18 deletions

View File

@ -1,29 +1,84 @@
import express from 'express';
import type { NextFunction, Request, Response } from 'express';
import cors from 'cors';
import { getBuildConfig } from './util.js';
import { context } from 'esbuild';
import chokidar from 'chokidar';
const mermaidCtx = await context(
getBuildConfig({ minify: false, core: false, entryName: 'mermaid' })
);
const mermaidIIFECtx = await context(
getBuildConfig({ minify: false, core: false, entryName: 'mermaid', format: 'iife' })
);
const externalCtx = await context(
getBuildConfig({ minify: false, core: false, entryName: 'mermaid-example-diagram' })
);
const zenumlCtx = await context(
getBuildConfig({ minify: false, core: false, entryName: 'mermaid-zenuml' })
);
const contexts = [mermaidCtx, mermaidIIFECtx, externalCtx, zenumlCtx];
const rebuildAll = async () => {
await Promise.all(contexts.map((ctx) => ctx.rebuild()));
};
let clients: { id: number; response: Response }[] = [];
function eventsHandler(request: Request, response: Response, next: NextFunction) {
const headers = {
'Content-Type': 'text/event-stream',
Connection: 'keep-alive',
'Cache-Control': 'no-cache',
};
response.writeHead(200, headers);
const clientId = Date.now();
clients.push({
id: clientId,
response,
});
request.on('close', () => {
clients = clients.filter((client) => client.id !== clientId);
});
}
let timeoutId: NodeJS.Timeout | undefined = undefined;
/**
* Debounce file change events to avoid rebuilding multiple times.
*/
function handleFileChange() {
if (timeoutId !== undefined) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(async () => {
await rebuildAll();
sendEventsToAll();
timeoutId = undefined;
}, 100);
}
function sendEventsToAll() {
clients.forEach(({ response }) => response.write(`data: ${Date.now()}\n\n`));
}
async function createServer() {
const app = express();
const mermaidCtx = await context(
getBuildConfig({ minify: false, core: false, entryName: 'mermaid' })
);
const mermaidIIFECtx = await context(
getBuildConfig({ minify: false, core: false, entryName: 'mermaid', format: 'iife' })
);
const externalCtx = await context(
getBuildConfig({ minify: false, core: false, entryName: 'mermaid-example-diagram' })
);
const zenuml = await context(
getBuildConfig({ minify: false, core: false, entryName: 'mermaid-zenuml' })
);
mermaidCtx.watch();
mermaidIIFECtx.watch();
externalCtx.watch();
zenuml.watch();
chokidar
.watch('**/src/**/*.{js,ts,yaml,json}', {
ignoreInitial: true,
ignored: [/node_modules/, /dist/, /docs/, /coverage/],
})
.on('all', async (event, path) => {
// Ignore other events.
if (!['add', 'change'].includes(event)) {
return;
}
console.log(`${path} changed. Rebuilding...`);
handleFileChange();
});
app.use(cors());
app.get('/events', eventsHandler);
app.use(express.static('./packages/mermaid/dist'));
app.use(express.static('./packages/mermaid-zenuml/dist'));
app.use(express.static('./packages/mermaid-example-diagram/dist'));

View File

@ -30,5 +30,33 @@ graph TB
console.log(svg);
el.innerHTML = svg;
</script>
<script>
// Set to false to disable live reload
const liveReload = true;
// Connect to the server and reload the page if the server sends a reload message
const connectToEvents = () => {
const events = new EventSource('/events');
const loadTime = Date.now();
events.onmessage = (event) => {
const time = JSON.parse(event.data);
if (time && time > loadTime) {
location.reload();
}
};
events.onerror = (error) => {
console.error(error);
events.close();
// Try to reconnect after 1 second in case of errors
setTimeout(connectToEvents, 1000);
};
events.onopen = () => {
console.log('Connected to live reload server');
};
};
if (liveReload) {
connectToEvents();
}
</script>
</body>
</html>

View File

@ -15,7 +15,7 @@
"git graph"
],
"scripts": {
"build": "pnpm build:esbuild && pnpm build:types",
"build": "pnpm run -r clean && pnpm build:esbuild && pnpm build:types",
"build:esbuild": "pnpm run -r clean && ts-node-esm --transpileOnly .esbuild/build.ts",
"build:mermaid": "pnpm build:esbuild --mermaid",
"build:viz": "pnpm build:esbuild --visualize",
@ -82,6 +82,7 @@
"@vitest/spy": "^0.33.0",
"@vitest/ui": "^0.33.0",
"ajv": "^8.12.0",
"chokidar": "^3.5.3",
"concurrently": "^8.0.1",
"cors": "^2.8.5",
"cypress": "^12.10.0",

View File

@ -74,6 +74,9 @@ importers:
ajv:
specifier: ^8.12.0
version: 8.12.0
chokidar:
specifier: ^3.5.3
version: 3.5.3
concurrently:
specifier: ^8.0.1
version: 8.0.1