hono-jsx-router v1.5.0
JSXRouter
JSXRouter
is a file-based router for Hono.js with the JSX middleware.
Table of Contents
Installation
npm i --save hono-jsx-router
Usage
import { Hono } from 'hono';
import { JSXRouter } from 'hono-jsx-router';
const jsxRouter: JSXRouter<any> = new JSXRouter({
config: {
// JSXRouter config
}
});
const app = new Hono({
router: jsxRouter
});
jsxRouter.applyRoutes();
Config
package.json
:
{
//...
"scripts": {
"build": "npx jsx-combine"
},
"dependencies": {
"hono": "^3.2.0",
"hono-jsx-router": "^1.3.0"
},
"jsxRouter": {
"path": "src/routes"
}
}
index.ts
:
import { Hono } from 'hono';
import { JSXRouter } from 'hono-jsx-router';
const jsxRouter: JSXRouter<any> = new JSXRouter({
config: {
layout: {
// layout config
props: {
// props that can be passed to layouts
}
},
page: {
// page config
props: {
// props that can be passed to pages
}
}
}
});
const app = new Hono({
router: jsxRouter
});
jsxRouter.applyRoutes();
The props
object can take strings or functions as values. If the value is a function, the Context object is passed to it.
Pages
In the directory configured as path
in your package.json
, place JSX files (.tsx
). If you configure path
to be ./src/routes
, then JSXRouter will serve the files found there, The names should reflect the desired route. For example, if you have a file called about.tsx
, and you are using JSXRouter at /
of your site, this file will be served at /about
.
Subfolders
You can have multiple folders as needed, for when you need multiple subpages under /about
, you can create an about
folder and put as many subpages there that you need.
Wildcards
You can also add files that has a wildcard in its name to catch all routes that aren't handled by sibling files. So you can have a directory structure like:
src/routes/about/
./index.tsx
./other_page.tsx
./*.tsx
You will end up with routes to /about/
, /about/other_page/
, and /about/*
. The wildcard does not override the other two routes here.
Layout
You can provide a common layout in a file called _layout.tsx
. This will be used to wrap every page in the directory. Here is an example layout:
import { html } from 'hono/html';
export default (props: { children?: any }) => {
return html`<!DOCTYPE html>
<html lang="EN-US">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta name="theme-color" media="(prefers-color-scheme: light)" content="lightgray" />
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="gray" />
<title>Example Site</title>
<link rel="icon" href="/favicon.svg" sizes="any" type="image/svg+xml" />
</head>
<body>${props.children}</body>
</html>`;
};
It is recommended to create a components
directory alongside your routes
directory, placing JSX files there to be imported into your pages. For example, say you have src/components/Header.tsx
, it could contain something like this:
export default (props: { children?: any }) => {
return (
<header>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/blog">Blog</a>
</header>
)
}
Then you can use it in a page, like src/routes/index.tsx
:
import Header from '../components/Header';
export default (props: {}) => {
return (<>
<Header />
<h1>Home</h1>
<p>Hello world!</p>
</>)
};
Context
Each page has access to Hono's Context object via props
. Declare it like this to use it:
import type { Context } from 'hono';
export default (props: { c: Context }) => {
// ...
};
Fallback Routers
When using the basic import of JSXRouter, it will use Hono's LinearRouter to handle routes not found in the file structure. You can pick a different router depending on your use case by importing from one of the presets:
- LinearRouter:
import { JSXRouter } from 'hono-jsx-router/linear';
- PatternRouter:
import { JSXRouter } from 'hono-jsx-router/pattern';
- RegExpRouter:
import { JSXRouter } from 'hono-jsx-router/reg-exp';
- SmartRouter*:
import { JSXRouter } from 'hono-jsx-router/smart';
- TrieRouter:
import { JSXRouter } from 'hono-jsx-router/trie';
*When using the SmartRouter, you will need to specify the routers it should pick from:
import { Hono } from 'hono';
import { JSXRouter } from 'hono-jsx-router/smart';
const jsxRouter: JSXRouter<any> = new JSXRouter({
config: {
// JSXRouter config
},
routers: [
new RegExpRouter(),
new TrieRouter()
]
});
Query Parameters
A JSX page can receive query parameters. To access them, add params
to your props
argument, like below:
export default (props: { params:? Record<string, string[]> }) => {
//...
};
Then you can access the query parameters anywhere in the page. For example, if a user browses to /?foo=bar&abc=xyz
, you can access these query parameters like so:
export default (props: { params:? Record<string, string[]> }) => {
return (<>
<h1>Home</h1>
<p>Hello world!</p>
<p>You query for foo is {props.params.foo[0]} and your query for abc is {props.params.abc[0]}.</p>
</>)
};
This will result in the following HTML:
<h1>Home</h1>
<p>Hello world!</p>
<p>You query for foo is bar and your query for abc is xyz.</p>
Since the params are string arrays (string[]
), if there are multiple instances of a key in a query, all of the values can be accessed in order by index. Internally, this uses HonoRequest.queries()
.
Known Issues
- Need to add a way to set per page
<head>
attributes. - Subfolder layouts are not currently supported, but is a planned feature.
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago