Skip to content

Commit

Permalink
dev fast refresh
Browse files Browse the repository at this point in the history
  • Loading branch information
cblanquera committed Aug 22, 2024
1 parent 61af842 commit 640e9cd
Show file tree
Hide file tree
Showing 22 changed files with 942 additions and 178 deletions.
21 changes: 14 additions & 7 deletions packages/temple-dev/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,30 @@ var temple_dev = (() => {
__export(client_exports, {
default: () => client
});
function client(options = {}, wait = 0) {
function client(id, options = {}, wait = 0) {
const { path = "/__temple_dev__" } = options;
const source = new EventSource(path);
source.addEventListener("refresh", () => {
window.location.reload();
source.addEventListener("refresh", (message) => {
const data = JSON.parse(message.data);
if (!data[id]) return;
data[id].forEach((code) => {
try {
const script = new Function(code);
script();
} catch (e) {
console.error(e);
}
});
});
source.onopen = () => {
if (wait > 0) {
console.clear();
console.log("Connection re-established.");
window.location.reload();
}
wait = 0;
};
source.onerror = () => {
source.close();
if (wait < 1e4) {
setTimeout(() => client(options, wait + 2e3), wait);
setTimeout(() => client(id, options, wait + 2e3), wait);
} else {
console.error(
"Too many connection attempts. Please check your server and refresh page."
Expand Down
1 change: 1 addition & 0 deletions packages/temple-dev/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
},
"dependencies": {
"@blanquera/types": "1.0.2",
"@ossph/temple": "0.0.15",
"chokidar": "3.6.0",
"ws": "8.17.0"
},
Expand Down
82 changes: 76 additions & 6 deletions packages/temple-dev/src/sse/RefreshServer.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
import { FSWatcher } from 'chokidar';
import { ServerOptions, OptionIgnore, Request, Response } from './types';

import type { FSWatcher } from 'chokidar';
import type {
ServerOptions,
OptionIgnore,
Request,
Response,
Props
} from './types';

import path from 'path';
import chokidar from 'chokidar';
import { Component, DocumentBuilder } from '@ossph/temple/compiler';
import { dependantsOf, update } from './helpers';

const extensions = [ '.tml', '.ts', '.js', '.json', '.css' ];
const extensions = [ '.tml', '.dtml', '.ts', '.js', '.json', '.css' ];

/**
* Socket server to be used in node
*/
export default class RefreshServer {
//active build and props
protected _registry = new Map<string, {
builder: DocumentBuilder,
props: Props
}>();
//the current working directory
protected _cwd: string;
//file extensions to listen to
Expand Down Expand Up @@ -39,6 +53,13 @@ export default class RefreshServer {
this._ignore = options.ignore || [];
}

/**
* Registers rendered document builder
*/
public register(builder: DocumentBuilder, props: Props) {
this._registry.set(builder.document.absolute, { builder, props });
}

/**
* Closes the socket connection
*/
Expand All @@ -58,15 +79,64 @@ export default class RefreshServer {
/**
* Tell all the browsers to reload their page
*/
public refresh(filepath: string) {
const extname = path.extname(filepath);
public async refresh(filePath: string) {
const extname = path.extname(filePath);
if (!this._extensions.includes(extname)) {
return this;
}

//what file changed?
//what components import this file?
//what document imports this component?
const absolute = path.resolve(this._cwd, filePath);
const updates: Record<string, string[]> = {};

//loop through the registry
for (const { builder } of this._registry.values()) {
const document = builder.document;
//if the document is the same as the changed file
if (document.absolute === absolute) {
//just reload
updates[document.id] = [ 'window.location.reload();' ];
continue;
}
//get any dependencies that import this file
const dependants = dependantsOf(absolute, document);
//if there are no dependants, skip
if (dependants.length === 0) {
continue;
}

updates[document.id] = [];
for (const dependant of dependants) {
//if the filePath was imported as a component
if (dependant.type === 'component') {
//update the imported component
const component = new Component(absolute, {
brand: document.brand,
cwd: document.cwd,
fs: document.fs,
seed: document.seed
});
const script = await update(component);
updates[document.id].push(script);
continue;
//if the parent component is a component
} else if (dependant.component.type === 'component') {
//the filePath was imported as a template
// or file, update the parent component
const script = await update(dependant.component);
updates[document.id].push(script);
continue;
}

updates[document.id].push('window.location.reload();');
}
};

this._clients.forEach(res => {
res.write("event: refresh\n");
res.write("data: 1\n\n");
res.write(`data: ${JSON.stringify(updates)}\n\n`);
//if this works, then the browser will reload
//causing the req.close event to be triggered
//and the client will be removed from the list
Expand Down
21 changes: 14 additions & 7 deletions packages/temple-dev/src/sse/client.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,31 @@
import type { ClientOptions } from './types';

export default function client(options: ClientOptions = {}, wait = 0) {
export default function client(id: string, options: ClientOptions = {}, wait = 0) {
const { path = '/__temple_dev__' } = options;
const source = new EventSource(path);
source.addEventListener('refresh', () => {
window.location.reload();
source.addEventListener('refresh', message => {
const data = JSON.parse(message.data) as Record<string, string[]>;
if (!data[id]) return;
data[id].forEach(code => {
try {
const script = new Function(code);
script();
} catch (e) {
console.error(e);
}
});
});

source.onopen = () => {
if (wait > 0) {
console.clear();
console.log('Connection re-established.')
window.location.reload();
}
wait = 0;
};

source.onerror = () => {
source.close();
if (wait < 10000) {
setTimeout(() => client(options, wait + 2000), wait);
setTimeout(() => client(id, options, wait + 2000), wait);
} else {
console.error(
'Too many connection attempts. Please check your server and refresh page.'
Expand Down
Loading

0 comments on commit 640e9cd

Please sign in to comment.