improved middlewares + added _layout support
This commit is contained in:
parent
b8107c8f04
commit
4cc9669468
|
|
@ -15,10 +15,6 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"lightningcss": "^1.29.1",
|
||||
"pokedex-promise-v2": "^4.2.1",
|
||||
"serve-static-bun": "^0.5.3",
|
||||
"tree-sitter-cli": "^0.25.2",
|
||||
"tree-sitter-typescript": "^0.23.2",
|
||||
"web-tree-sitter": "^0.25.2"
|
||||
"serve-static-bun": "^0.5.3"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,23 @@
|
|||
import { myPlugin } from "./myPlugin";
|
||||
import { fillTemplate, render } from "./lib/fast-web";
|
||||
import {
|
||||
fillTemplate,
|
||||
render,
|
||||
resolveLayoutPaths,
|
||||
wrapLayouts,
|
||||
} from "./lib/fast-web";
|
||||
import { requestLog } from "./middlewares/request-log";
|
||||
import template from "./template.html" with { type: "text" };
|
||||
import theme from "./theme.css" with { type: "text" };
|
||||
import staticDir from "serve-static-bun";
|
||||
import path from "path";
|
||||
import { withMiddlewares } from "./middlewares/with-middlewares";
|
||||
import { gzip } from "./middlewares/gzip";
|
||||
|
||||
const pagesDir = __dirname + "/pages";
|
||||
|
||||
const router = new Bun.FileSystemRouter({
|
||||
style: "nextjs",
|
||||
dir: __dirname + "/pages",
|
||||
dir: pagesDir,
|
||||
});
|
||||
|
||||
const staticPublic = staticDir("./public");
|
||||
|
|
@ -16,16 +26,24 @@ const scriptsGlob = new Bun.Glob(__dirname + "/scripts/*");
|
|||
|
||||
const server = Bun.serve({
|
||||
port: 8080,
|
||||
fetch: requestLog(async (req): Promise<Response> => {
|
||||
fetch: withMiddlewares(
|
||||
async (req): Promise<Response> => {
|
||||
if (req.url.endsWith("ws")) {
|
||||
if (server.upgrade(req)) return new Response("ok");
|
||||
}
|
||||
|
||||
const match = router.match(req);
|
||||
if (!match) return staticPublic(req);
|
||||
const Comp = (await import(__dirname + "/pages/" + match?.pathname))
|
||||
.default;
|
||||
const renderResult = await render(<Comp />, [theme], new URL(req.url));
|
||||
const layouts = await resolveLayoutPaths(
|
||||
path.join(pagesDir, match.src),
|
||||
pagesDir,
|
||||
);
|
||||
const Comp = (await import(path.join(pagesDir, match.src))).default;
|
||||
const renderResult = await render(
|
||||
await wrapLayouts(<Comp />, layouts),
|
||||
[theme],
|
||||
new URL(req.url),
|
||||
);
|
||||
|
||||
const systemScripts = await Bun.build({
|
||||
entrypoints: [
|
||||
|
|
@ -47,15 +65,16 @@ const server = Bun.serve({
|
|||
body: renderResult.html,
|
||||
});
|
||||
|
||||
const gzipResponseData = Bun.gzipSync(responseData);
|
||||
|
||||
return new Response(gzipResponseData, {
|
||||
return new Response(responseData, {
|
||||
headers: {
|
||||
"content-type": "text/html",
|
||||
"Content-Encoding": "gzip",
|
||||
},
|
||||
});
|
||||
}),
|
||||
},
|
||||
requestLog(),
|
||||
gzip,
|
||||
requestLog("gzip"),
|
||||
),
|
||||
websocket: {
|
||||
message: () => {},
|
||||
open: async (ws) => {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { camelToKebab, renderStyle } from "~/system/style-rules";
|
|||
import { transform } from "lightningcss";
|
||||
import reset from "./reset.css" with { type: "text" };
|
||||
import { AsyncLocalStorage } from "async_hooks";
|
||||
import path from "path";
|
||||
|
||||
interface RenderContext {
|
||||
styles: string[];
|
||||
|
|
@ -122,3 +123,27 @@ export const fillTemplate = (
|
|||
return acc.replace(`<!-- ${key} -->`, value);
|
||||
}, template);
|
||||
};
|
||||
|
||||
export const resolveLayoutPaths = async (file: string, rootDir: string) => {
|
||||
const layouts = [];
|
||||
let dir = file;
|
||||
console.log(path.normalize(dir));
|
||||
console.log(path.normalize(rootDir));
|
||||
do {
|
||||
dir = path.join(dir, "..");
|
||||
const layoutFile = path.join(dir, "_layout.tsx");
|
||||
if (await Bun.file(layoutFile).exists()) {
|
||||
layouts.push(layoutFile);
|
||||
}
|
||||
} while (path.normalize(dir) != path.normalize(rootDir));
|
||||
return layouts;
|
||||
};
|
||||
|
||||
export const wrapLayouts = async (element: JSX.Element, layouts: string[]) => {
|
||||
let wrapped = element;
|
||||
for (const part of layouts) {
|
||||
const Layout = (await import(part)).default;
|
||||
wrapped = <Layout>{wrapped}</Layout>;
|
||||
}
|
||||
return wrapped;
|
||||
};
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
export const gzip = (handler: (req: Request) => Promise<Response>) => {
|
||||
return async (req: Request) => {
|
||||
const response = await handler(req);
|
||||
const bytes = await response.clone().bytes();
|
||||
const gzipped = Bun.gzipSync(bytes);
|
||||
return new Response(gzipped, {
|
||||
headers: { ...response.headers.toJSON(), "Content-Encoding": "gzip" },
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
});
|
||||
};
|
||||
};
|
||||
|
|
@ -11,15 +11,16 @@ const formatBytes = (bytes: number) => {
|
|||
return bytes + "B";
|
||||
};
|
||||
|
||||
export const requestLog = (handler: (req: Request) => Promise<Response>) => {
|
||||
export const requestLog =
|
||||
(name?: string) => (handler: (req: Request) => Promise<Response>) => {
|
||||
return async (req: Request) => {
|
||||
const start = performance.now();
|
||||
const response = await handler(req);
|
||||
const bytes = await response.clone().bytes();
|
||||
const delta = performance.now() - start;
|
||||
console.log(
|
||||
`[${req.method}] ${req.url} -> ${response.headers.get("Content-Type")} ${formatBytes(bytes.length)} in ${delta}ms`,
|
||||
`[${req.method}] ${req.url}${name ? " " + name : ""} -> ${response.headers.get("Content-Type")} ${formatBytes(bytes.length)} in ${delta}ms`,
|
||||
);
|
||||
return response;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
type Handler = (req: Request) => Promise<Response>;
|
||||
|
||||
export const withMiddlewares = (
|
||||
fetchFn: Handler,
|
||||
...handlers: ((handler: Handler) => Handler)[]
|
||||
) => {
|
||||
return async (req: Request) => {
|
||||
return handlers.reduce((acc, c) => {
|
||||
return c(acc);
|
||||
}, fetchFn)(req);
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import Layout from "../components/Layout";
|
||||
|
||||
export default Layout;
|
||||
|
|
@ -12,7 +12,6 @@ export default async function Index() {
|
|||
offset: page * 20,
|
||||
});
|
||||
return (
|
||||
<Layout>
|
||||
<>
|
||||
<div>Hello World</div>
|
||||
<Counter />
|
||||
|
|
@ -25,6 +24,5 @@ export default async function Index() {
|
|||
<Link href={`/?page=${page - 1}`}>Prev</Link>
|
||||
<Link href={`/?page=${page + 1}`}>Next</Link>
|
||||
</>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue