-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #212 from sejori/example-architecture
feat: cleaned preactSSR example
- Loading branch information
Showing
7 changed files
with
127 additions
and
121 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { Handler, file } from "../../../mod.ts"; | ||
|
||
const base = `https://raw.githubusercontent.com/sejori/peko/main/example/preactSSR`; | ||
|
||
export const githubHandler = | ||
(path: string, type?: string): Handler => | ||
async (ctx) => | ||
( | ||
await file( | ||
ctx.state.env.ENVIRONMENT === "production" | ||
? new URL(`${base}${path}`) | ||
: new URL("../" + path, import.meta.url), | ||
{ | ||
headers: new Headers({ | ||
...(type && { "Content-Type": type }), | ||
// instruct browser to cache file in prod env | ||
"Cache-Control": | ||
ctx.state.env.ENVIRONMENT === "production" | ||
? "max-age=86400, stale-while-revalidate=86400" | ||
: "no-store", | ||
}), | ||
} | ||
) | ||
)(ctx); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { Handler } from "../../../mod.ts"; | ||
|
||
export const parrotHandler: Handler = async (ctx) => { | ||
const reader = ctx.request.body?.getReader(); | ||
let result = ""; | ||
const chunkSize = 1024; | ||
|
||
if (reader) { | ||
let done = false; | ||
while (!done) { | ||
const { value, done: chunkDone } = await reader.read(); | ||
if (value) { | ||
result += new TextDecoder().decode(value); | ||
if (result.length >= chunkSize) { | ||
result = result.slice(0, chunkSize); | ||
break; | ||
} | ||
} | ||
done = chunkDone; | ||
} | ||
} | ||
|
||
return new Response(`Parrot sqwarks: ${result}`); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { renderToString } from "preact-render-to-string"; | ||
import { Handler, ssr } from "../../../mod.ts"; | ||
import htmlTemplate from "../src/document.ts"; | ||
|
||
export const preactHandler = | ||
( | ||
component: (props: Record<string, unknown>) => unknown, | ||
title: string, | ||
entrypoint: string | ||
): Handler => | ||
(ctx) => { | ||
return ssr( | ||
() => { | ||
const ssrHTML = renderToString(component(ctx.state), null, null); | ||
return htmlTemplate({ | ||
title, | ||
ssrHTML, | ||
entrypoint, | ||
serverState: ctx.state, | ||
}); | ||
}, | ||
{ | ||
headers: new Headers({ | ||
// instruct browser to cache page in prod env | ||
"Cache-Control": | ||
ctx.state.env.ENVIRONMENT === "production" | ||
? "max-age=86400, stale-while-revalidate=86400" | ||
: "no-store", | ||
}), | ||
} | ||
)(ctx); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { Handler, sse } from "../../../mod.ts"; | ||
|
||
const demoEventTarget = new EventTarget(); | ||
export const randomEventHandler: Handler = (ctx) => { | ||
setInterval(() => { | ||
demoEventTarget.dispatchEvent( | ||
new CustomEvent("send", { detail: Math.random() }) | ||
); | ||
}, 2500); | ||
|
||
return sse(demoEventTarget)(ctx); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { Middleware } from "../../../mod.ts"; | ||
|
||
export const reqTime: Middleware = (ctx) => { | ||
ctx.state = { | ||
env: ctx.state.env, | ||
request_time: `${Date.now()}`, | ||
DENO_REGION: ctx.state.env.DENO_REGION, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,137 +1,42 @@ | ||
import { | ||
Router, | ||
RequestContext, | ||
logger, | ||
sse, | ||
cacher, | ||
ssr, | ||
file, | ||
} from "../../mod.ts"; //"https://deno.land/x/peko/mod.ts" | ||
import { renderToString } from "preact-render-to-string"; | ||
|
||
import Home from "./src/pages/Home.ts"; | ||
import { Router, logger, cacher } from "../../mod.ts"; //"https://deno.land/x/peko/mod.ts" | ||
import { preactHandler } from "./handlers/preact.handler.ts"; | ||
import { githubHandler } from "./handlers/github.handler.ts"; | ||
import { reqTime } from "./middleware/reqTime.middleware.ts"; | ||
import { randomEventHandler } from "./handlers/rdmEvent.handler.ts"; | ||
import { parrotHandler } from "./handlers/parrot.handler.ts"; | ||
import About from "./src/pages/About.ts"; | ||
import htmlTemplate from "./document.ts"; | ||
import Home from "./src/pages/Home.ts"; | ||
|
||
const router = new Router(); | ||
router.use(logger(console.log)); | ||
|
||
// SSR example, with cache bc static page | ||
router.get("/", { | ||
middleware: cacher(), | ||
handler: (ctx) => { | ||
return ssr( | ||
() => { | ||
const ssrHTML = renderToString(Home(), null, null); | ||
return htmlTemplate({ | ||
title: "Peko", | ||
ssrHTML, | ||
entrypoint: "/src/pages/Home.ts", | ||
}); | ||
}, | ||
{ | ||
headers: new Headers({ | ||
// instruct browser to cache page in prod env | ||
"Cache-Control": | ||
ctx.state.env.ENVIRONMENT === "production" | ||
? "max-age=86400, stale-while-revalidate=86400" | ||
: "no-store", | ||
}), | ||
} | ||
)(ctx); | ||
}, | ||
}); | ||
// SSR, with cache because static page | ||
router.get("/", cacher(), preactHandler(Home, "Peko", "/src/pages/Home.ts")); | ||
|
||
// SSR example, no cache because dynamic content | ||
// (About page renders server state into HTML) | ||
// SSR, no cache because dynamic content | ||
router.get( | ||
"/about", | ||
(ctx) => { | ||
ctx.state = { | ||
request_time: `${Date.now()}`, | ||
...ctx.state.env, | ||
}; | ||
}, | ||
ssr((ctx) => { | ||
const ssrHTML = renderToString(About(ctx.state), null, null); | ||
return htmlTemplate({ | ||
title: "Peko | About", | ||
ssrHTML, | ||
entrypoint: "/src/pages/About.ts", | ||
serverState: ctx.state, | ||
}); | ||
}) | ||
reqTime, | ||
preactHandler(About, "Peko | About", "/src/pages/About.ts") | ||
); | ||
|
||
// Static file example | ||
// dynamic URL param for filename, always cache | ||
router.get("/assets/:filename", cacher(), async (ctx) => | ||
( | ||
await file( | ||
new URL( | ||
`https://raw.githubusercontent.com/sejori/peko/main/example/preactSSR/assets/${ctx.params.filename}` | ||
), | ||
{ | ||
headers: new Headers({ | ||
// instruct browser to cache file in prod env | ||
"Cache-Control": | ||
ctx.state.env.ENVIRONMENT === "production" | ||
? "max-age=86400, stale-while-revalidate=86400" | ||
: "no-store", | ||
}), | ||
} | ||
) | ||
)(ctx) | ||
// Static, URL param for filename, always cache | ||
router.get("/assets/:filename", cacher(), (ctx) => | ||
githubHandler(`/assets/${ctx.params.filename}`)(ctx) | ||
); | ||
|
||
// Return transformed source code example | ||
// dynamic URL param for filename, always cache, transformed with esbuild at build time | ||
router.get("/src/:dirname/:filename", cacher(), async (ctx) => { | ||
const transformedFilename = ctx.params.filename.replace(".ts", ".js"); | ||
return ( | ||
await file( | ||
ctx.state.env.ENVIRONMENT === "production" | ||
? new URL( | ||
`https://raw.githubusercontent.com/sejori/peko/main/example/preactSSR/dist/${ctx.params.dirname}/${transformedFilename}` | ||
) | ||
: new URL( | ||
`./dist/${ctx.params.dirname}/${transformedFilename}`, | ||
import.meta.url | ||
), | ||
{ | ||
headers: new Headers({ | ||
"Content-Type": "application/javascript", | ||
// instruct browser to cache file in prod env | ||
"Cache-Control": | ||
ctx.state.env.ENVIRONMENT === "production" | ||
? "max-age=86400, stale-while-revalidate=86400" | ||
: "no-store", | ||
}), | ||
} | ||
) | ||
)(ctx); | ||
}); | ||
|
||
// Server-sent events example | ||
const demoEventTarget = new EventTarget(); | ||
router.get("/sse", (ctx: RequestContext) => { | ||
setInterval(() => { | ||
demoEventTarget.dispatchEvent( | ||
new CustomEvent("send", { detail: Math.random() }) | ||
); | ||
}, 2500); | ||
// Transformed src at build-time with esbuild, always cache | ||
router.get("/src/:dirname/:filename", cacher(), (ctx) => | ||
githubHandler( | ||
`/dist/${ctx.params.dirname}/${ctx.params.filename.replace(".ts", ".js")}`, | ||
"application/javascript" | ||
)(ctx) | ||
); | ||
|
||
return sse(demoEventTarget)(ctx); | ||
}); | ||
// Server-sent events demo | ||
router.get("/sse", randomEventHandler); | ||
|
||
// .addRoute example | ||
router.addRoute({ | ||
path: "/api/parrot", | ||
method: "POST", | ||
handler: async (ctx: RequestContext) => { | ||
const body = await ctx.request.text(); | ||
return new Response(`Parrot sqwarks: ${body}`); | ||
}, | ||
}); | ||
// Basic | ||
router.post("/parrot", parrotHandler); | ||
|
||
export default router; |
File renamed without changes.