- Route is: {routeGet.Path.toString()}
+ Component Route is: {routeGet.Path.toString()}
- Component!!!
a link
Data:{Data && (Data as CatFact)?.fact}
Status:{Updating?'loading':'done'}
diff --git a/lib/iso.tsx b/lib/iso.tsx
index 071cbd7..2989821 100644
--- a/lib/iso.tsx
+++ b/lib/iso.tsx
@@ -161,6 +161,8 @@ export const Case =({children, value}:{children:Children, value?:string, default
export const useRouteVars =()=> React.useContext(SwitchContext).keys;
export type FetchRecord = {URL:string, CacheFor:number, CachedAt:number, CacheOnServer:boolean, Promise?:Promise
, DelaySSR:boolean, Seed:boolean, Error?:string, JSON?:object};
+type FetchGuide = [Record:FetchRecord, Init:boolean, Listen:boolean];
+export type FetchHookState = [Data:undefined|object, Updating:boolean];
export const Fetch = {
Cache:new Map() as Map,
ServerBlocking:false as false|Promise[],
@@ -169,11 +171,11 @@ export const Fetch = {
Seed(seed:FetchRecord[])
{
seed.forEach(r=>{
- r.Promise = Promise.resolve(r);
+ //r.Promise = Promise.resolve(r);
Fetch.Cache.set(r.URL, r)
});
},
- Request(URL:string, Init?:RequestInit, CacheFor:number = 60, CacheOnServer:boolean = true, DelaySSR:boolean = true, Seed:boolean = true)
+ Request(URL:string, Init?:RequestInit, CacheFor:number = 60, CacheOnServer:boolean = true, DelaySSR:boolean = true, Seed:boolean = true):FetchGuide
{
let check = Fetch.Cache.get(URL);
@@ -188,17 +190,24 @@ export const Fetch = {
return inCheck;
});
return inCheck;
- }
+ };
if(!check)
{
+ // not in the cache
+ // - listen
+
console.log(`making new cache record...`);
- return load({URL, CacheFor, CachedAt:0, CacheOnServer, DelaySSR, Seed});
+ return [load({URL, CacheFor, CachedAt:0, CacheOnServer, DelaySSR, Seed}), false, true];
}
else if(check.CachedAt == 0)
{
+ // loading started but not finished
+ // - listen
+ // - possibly init if there is something in JSON
+
console.log(`currently being cached...`);
- return check;
+ return [check, check.JSON ? true : false, true];
}
else
{
@@ -206,38 +215,49 @@ export const Fetch = {
let secondsAge = (new Date().getTime() - check.CachedAt)/1000;
if(secondsAge > check.CacheFor)
{
+ // cached but expired
+ // - listen
+ // - init
console.log(`...outdated...`);
- return load(check);
+ return [load(check), true, true];
}
else
{
+ // cached and ready
+ // - init
console.log(`...retrieved!`);
- return check;
+ return [check, true, false];
}
}
},
Use(URL:string, Init?:RequestInit, CacheFor:number = 60, CacheOnServer:boolean = true, DelaySSR:boolean = true, Seed:boolean = true)
{
- type FetchHookState = [Data:undefined|object, Updating:boolean];
- const [cacheGet, cacheSet] = React.useState([undefined, true] as FetchHookState);
- if(Fetch.ServerBlocking && Fetch.ServerTouched && DelaySSR)
+ const [receipt, init, listen] = Fetch.Request(URL, Init, CacheFor, CacheOnServer, DelaySSR, Seed);
+ const initialState:FetchHookState = init ? [receipt.JSON, listen] : [undefined, true];
+ const [cacheGet, cacheSet] = React.useState(initialState);
+
+ if(Fetch.ServerBlocking && Fetch.ServerTouched && DelaySSR) // if server-side rendering
{
- const receipt = Fetch.Request(URL, Init, CacheFor, CacheOnServer, DelaySSR, Seed);
- if(receipt.CachedAt === 0 && receipt.Promise)// request for something that hasnt been cached yet
+ if(listen) // if the request is pending
{
- Fetch.ServerBlocking.push(receipt.Promise);
+ receipt.Promise && Fetch.ServerBlocking.push(receipt.Promise); // add promise to blocking list
+ return [undefined, listen] as FetchHookState; // no need to return any actual data while waiting server-side
}
- else if(receipt.Seed)
+ else // if request is ready
{
- Fetch.ServerTouched.add(receipt);
+ receipt.Seed && Fetch.ServerTouched.add(receipt); // add record to client seed list (if specified in receipt.seed)
+ return [receipt.JSON, false] as FetchHookState;
}
- return [receipt.JSON, receipt.CachedAt === 0];
}
+
React.useEffect(()=>
{
- const receipt = Fetch.Request(URL, Init, CacheFor, CacheOnServer, DelaySSR);
- receipt.Promise?.then(()=>cacheSet([receipt.JSON, receipt.CachedAt === 0]));
+ if(listen)
+ {
+ //const receipt = Fetch.Request(URL, Init, CacheFor, CacheOnServer, DelaySSR);
+ receipt.Promise?.then(()=>cacheSet([receipt.JSON, receipt.CachedAt === 0]));
+ }
}
, []);
diff --git a/server.tsx b/server.tsx
index 2aae3d6..7074a81 100644
--- a/server.tsx
+++ b/server.tsx
@@ -2,6 +2,7 @@ import * as ESBuild from 'https://deno.land/x/esbuild@v0.14.45/mod.js';
import * as MIME from "https://deno.land/std@0.180.0/media_types/mod.ts";
import { debounce } from "https://deno.land/std@0.151.0/async/debounce.ts";
import SSR from "https://esm.sh/v113/preact-render-to-string@6.0.2";
+import Prepass from "https://esm.sh/preact-ssr-prepass@1.2.0";
import * as Twind from "https://esm.sh/@twind/core@1.1.3";
import React from "react";
import * as Iso from "@eno/iso";
@@ -35,7 +36,8 @@ const Transpileable =(inFilePath:string):boolean=>
};
const Transpile =async(inCode:string, inKey:string):Promise=>
{
- const transpile = await ESBuild.transform(inCode, { loader: "tsx", minify:true});
+ const transpile = await ESBuild.transform(inCode, { loader: "tsx", sourcemap:"inline", minify:true, sourcefile:inKey});
+
Transpiled.set(inKey, transpile.code);
return transpile.code;
};
@@ -224,14 +226,18 @@ FileListen("${url.pathname}", reloadHandler);`;
Iso.Fetch.ServerBlocking = [];
Iso.Fetch.ServerTouched = new Set();
Iso.Fetch.ServerRemove = new Set();
- let bake = SSR();
+ let app = ;
+ await Prepass(app)
+ let bake = SSR(app);
while(Iso.Fetch.ServerBlocking.length)
{
await Promise.all(Iso.Fetch.ServerBlocking);
Iso.Fetch.ServerBlocking = [];
// at this point, anything that was requested that was not cached, has now been loaded and cached
// this next render will use cached resources. using a cached resource (if its "Seed" is true) adds it to the "touched" set.
- bake = SSR();
+ app = ;
+ await Prepass(app)
+ bake = SSR(app);
}
const seed:Iso.FetchRecord[] = [];
@@ -258,13 +264,13 @@ FileListen("${url.pathname}", reloadHandler);`;
${results.html}