Package Exports
- pranx
Readme
Pranx
The next of preact.
A light-weight, Next.js-like framework with Preact, Hono, and esbuild for static site generation and hydration.
Features
- File-System Based Routing
- Api handlers
- Static Site Generation (SSG)
- SSR
- Client Side Routing
- Client-Side Hydration
- Fully typescript support
- Hot Module Replacement (HMR)
- Fast compilation with esbuild
- CSS importing and automatic bundle
- Markdown and .mdx support
Usage
1- Create a hono project and select the nodejs adapter
npm create hono@latest2- Add pranx
npm install pranx@latest3- Update the tsconfig.json file
{
"compilerOptions": {
"target": "ESNext",
"module": "es2022",
"moduleResolution": "node",
"resolveJsonModule": true,
"declaration": true,
"outDir": "./dist",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noUnusedLocals": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUncheckedIndexedAccess": true,
"noUnusedParameters": true,
"jsx": "react-jsx",
"jsxImportSource": "preact",
"skipLibCheck": true,
"checkJs": true
},
"exclude": ["node_modules"],
"include": ["src"]
}4- Update the entry point, default should be src/index.ts
import { serve } from "@hono/node-server";
import { pranx } from "pranx";
const app = await pranx.init({
mode: "prod",
});
serve(
{
fetch: app.fetch,
port: Number(process.env.PORT) || 3030,
},
(info) => {
console.log(`Server is running on http://localhost:${info.port}`);
}
);5- Create the pranx.config.js file at the root of your project:
import { defineConfig } from "pranx";
export default defineConfig({});6- Done !!!
Routing
The routing system start with the definition of the pages path.
The default path is src/pages
It can be customize in the pranx.config.js file.
import { defineConfig } from "pranx";
export default defineConfig({
pages_dir: "",
public_dir: "",
});The public dir it's serve as it, for the server as statics and public assets. Will not be transformed.
The default path is public
Inside the pages folder each file name represents a part of the app.
page.{tsx,jsx,js,ts} -> The page that will be rendered as html and hydratated to the client.
route.{tsx,jsx,js,ts} -> Contains api handler only for the server.
The file path also represent the final url path that will be generated:
pages/page.tsx->/pages/blog/page.tsx->/blog/
Work in progress
pages/product/[id]/page.tsx->/product/:idpages/product/[...id]/page.tsx->/product/:id*
page.tsx
Can export several methods.
default-> page component will be renderedmeta-> meta description for theheadtaggetStaticPropsWork in progress
getStaticPathgetServerSideProps
Example:
pages/blog/page.tsx
import { GetStaticPropsResult } from "pranx";
import type { GetStaticProps, MetaFunction } from "pranx";
import { CounterButton } from "../../components/CounterButton";
import Layout from "../../layout/layout";
export const meta: MetaFunction = async () => {
return (
<>
<title>Blog | Pranx</title>
<link
rel="icon"
type="image/svg+xml"
href="/favicon.svg"
/>
</>
);
};
export const getStaticProps: GetStaticProps = async () => {
const data = await fetch("https://api.vercel.app/blog");
const posts = await data.json();
return {
props: {
posts,
},
};
};
export default function Page(props: GetStaticPropsResult["props"]) {
return (
<Layout>
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
gap: "10px",
}}
>
<h1>
This Blog Page Is Prerendered with <code>getStaticProps</code>
</h1>
<CounterButton />
<ul>
{props.posts.map((post: any) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
</Layout>
);
}route.ts
Can export api named methods that will be attached to hono server router
GETPOSTPUTPATCHDELETE
Example:
pages/api/product/[id]/route.ts
import type { PranxHandler } from "pranx";
export const GET: PranxHandler = (c) => {
const id = c.req.param("id");
return c.json({ id, method: "get" });
};
export const POST: PranxHandler = (c) => {
const id = c.req.param("id");
return c.json({ id, method: "post" });
};