Skip to content

Instantly share code, notes, and snippets.

@ycmjason
Last active October 27, 2024 13:29
Show Gist options
  • Save ycmjason/dfcc3ddfa34354a726304c7f5d019d65 to your computer and use it in GitHub Desktop.
Save ycmjason/dfcc3ddfa34354a726304c7f5d019d65 to your computer and use it in GitHub Desktop.
Deno Fresh Partial Fetch Events
export default () => {
const browserFetch = globalThis.fetch;
globalThis.fetch = async function (input, ...args) {
const urlOrUrlString = input instanceof Request ? input.url : input;
const url = new URL(urlOrUrlString);
const isPartialFetch = url.searchParams.get("fresh-partial") === "true";
if (isPartialFetch) {
globalThis.dispatchEvent(
new CustomEvent("beforePartialFetch", { detail: { url } }),
);
}
const response = await browserFetch(input, ...args);
if (isPartialFetch) {
globalThis.dispatchEvent(
new CustomEvent("afterPartialFetch", { detail: { url } }),
);
}
return response;
};
};
import type { Plugin } from "$fresh/server.ts";
import { dirname } from "@std/path";
import { join } from "@std/path/join";
export const partialFetchEventsPlugin = {
name: "partial-fetch-events",
entrypoints: {
client: join(dirname(import.meta.url), "client.ts"),
},
render(ctx) {
const res = ctx.render();
return {
...res,
scripts: [
{
entrypoint: "client",
state: {},
},
],
};
},
} satisfies Plugin;
import { useSignal } from "@preact/signals";
import { useEffect } from "preact/hooks";
export const PartialLoadingBar = () => {
const loadState = useSignal<"loading" | "loaded" | "not-loading">(
"not-loading",
);
useEffect(() => {
const onBeforePartialFetch = () => {
loadState.value = "loading";
};
const onAfterPartialFetch = () => {
loadState.value = "loaded";
setTimeout(() => {
loadState.value = "not-loading"; // careful! race condition possible
}, 500);
};
globalThis.addEventListener("beforePartialFetch", onBeforePartialFetch);
globalThis.addEventListener("afterPartialFetch", onAfterPartialFetch);
return () => {
globalThis.removeEventListener(
"beforePartialFetch",
onBeforePartialFetch,
);
globalThis.removeEventListener("afterPartialFetch", onAfterPartialFetch);
};
});
return (
<div
class={mixClasssssssss(
"h-1 w-[0%] bg-primary-500 transition-[width,opacity] duration-500 absolute z-40 top-0 left-0",
{
"not-loading": "opacity-0",
loading: "w-[30%] opacity-100",
loaded: "w-[100%] opacity-0",
}[loadState.value],
)}
/>
);
};
@ycmjason
Copy link
Author

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