Releases: rphlmr/react-router-hono-server
v2.7.1
What's Changed
Check: https://github.com/rphlmr/react-router-hono-server?tab=readme-ov-file#middleware
import { redirect } from "react-router-hono-server/http";
Full Changelog: v2.6.4...v2.7.0
v2.6.4
What's Changed
Full Changelog: v2.5.0...v2.6.0
- Add Vite 6 as a peer dependency (keeping Vite 5 too).
- Fix build loader for cloudflare
- Fix missing
AppLoadContext
in dev (dev server issue) - Add support for React Router
basename
- Handle React Router app as a Hono sub app
- [Cloudflare]: setting
experimental_serve_directly
in wrangler config will now use your Hono server to serve assets - Remove deprecated
honoOptions
in favor ofapp
option (createHonoServer
) - Temporary handle React Router issue (remix-run/react-router#12295)
Basename and Hono sub apps
Note
By default, the React Router app is mounted at /
(default basename
value).
You may not need to use this option. It's for advanced use cases.
Tip
Check this example to see how to use it.
You can use the basename
option in your React Router config (react-router.config.ts
) to mount your React Router app on a subpath.
It will automatically mount the app on the subpath.
// react-router.config.ts
import type { Config } from "@react-router/dev/config";
export default {
basename: "/app", // Now the React Router app will be mounted on /app
} satisfies Config;
Then, you can use the app
option in createHonoServer
to pass your "root" Hono app. This will be used to mount the React Router app on the basename
path.
import { Hono } from "hono";
import { createHonoServer } from "react-router-hono-server/node";
import { API_BASENAME, api } from "./api";
import { getLoadContext } from "./context";
// Create a root Hono app
const app = new Hono();
// Mount the API app at /api
app.route(API_BASENAME, api);
export default await createHonoServer({
// Pass the root Hono app to the server.
// It will be used to mount the React Router app on the `basename` defined in react-router.config.ts
app,
getLoadContext,
});
Note
You now have two entry points!
/api
- for your API/app
- for your React Router app
Cloudflare custom assets serving
You can set Cloudflare experimental_serve_directly
and delegate assets serving to Hono, like for Node and Bun.
Tip
Check https://developers.cloudflare.com/workers/static-assets/binding/#experimental_serve_directly
Tip
Check this example to see how to use it.
[assets]
directory = "./build/client/"
binding = "ASSETS"
experimental_serve_directly = false
v2.5.0
New
new helper: reactRouterRedirect
Redirect to a new location in a way that React Router can handle (Single fetch protocol).
🚨 Redirecting from a middleware
Important
You have to use the reactRouterRedirect
helper to redirect from a middleware.
It returns a single-fetch-like response.
If you use c.redirect
, it will not work as expected and you will get a Unable to decode turbo-stream response
error.
import { reactRouterRedirect } from "react-router-hono-server/http";
new createHonoServer option: beforeAll
You can use the beforeAll
option to add middleware that runs before any built-in middleware, including assets serving.
You can use it to add protection middleware, for example.
Tip
When you check the path to protect, don't forget to use c.req.path.includes("")
to handle .data
requests (loader
)!
import { reactRouterRedirect } from "react-router-hono-server/http";
import { createHonoServer } from "react-router-hono-server/node";
export default await createHonoServer({
beforeAll(app) {
app.use(async (c, next) => {
if (c.req.path.includes("/protected") && !c.req.header("Authorization")) {
return reactRouterRedirect("/login");
}
return next();
});
},
});
new createHonoServer option: overrideGlobalObjects
https://github.com/honojs/node-server?tab=readme-ov-file#overrideglobalobjects
It is now set to false
by default to prevent some issues with 3rd party libs like remix-hook-form
.
Enabling this makes request.clone()
not an instanceof Request
.
export default await createHonoServer({
overrideGlobalObjects: true,
});
Fixes
What's Changed
- added cloudflare d1-drizzle example by @diurivj in #45
- Handle Single fetch redirects by @rphlmr in #43
New Contributors
Full Changelog: v2.4.0...v2.5.0
v2.4.0
v2.3.0
What's Changed
Pre-rendering
You should be able to use pre-rendering with this package.
Tip
Check this example to see how to use it.
Important
You need to add the serverBuildFile
option to your react-router.config.ts
file.
The file path is fixed to assets/server-build.js
.
Add the prerender option to your react-router.config.ts
import type { Config } from "@react-router/dev/config";
export default {
serverBuildFile: "assets/server-build.js", // 🚨 Dont forget this
prerender: ["/"],
} satisfies Config;
Full Changelog: v2.2.1...v2.3.0
v2.2.1
v2.2.0
What's Changed
You can now enable WebSocket with the useWebSocket
option.
It works for node
and bun
. Cloudflare requires a custom implementation.
Take a look at all the examples.
import type { WSContext } from "hono/ws";
import { createHonoServer } from "react-router-hono-server/node";
// Store connected clients
const clients = new Set<WSContext>();
export default await createHonoServer({
useWebSocket: true,
// 👆 Unlock this 👇 from @hono/node-ws
configure: (app, { upgradeWebSocket }) => {
app.get(
"/ws",
upgradeWebSocket((c) => ({
// https://hono.dev/helpers/websocket
onOpen(_, ws) {
console.log("New connection ⬆️");
clients.add(ws);
},
onMessage(event, ws) {
console.log("Context", c.req.header("Cookie"));
console.log("Event", event);
console.log(`Message from client: ${event.data}`);
// Broadcast to all clients except sender
clients.forEach((client) => {
if (client.readyState === 1) {
client.send(`${event.data}`);
}
});
},
onClose(_, ws) {
console.log("Connection closed");
clients.delete(ws);
},
}))
);
},
});
Full Changelog: v2.1.2...v2.2.0
v2.1.2
What's Changed
Breaking change for Cloudflare
You need to install these packages too:
npm install -D miniflare wrangler
2.1.0
Bun
Tip
Check this example to see how to use it.
// vite.config.ts
import { reactRouter } from "@react-router/dev/vite";
import { reactRouterHonoServer } from "react-router-hono-server/dev"; // add this
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
export default defineConfig({
plugins: [
reactRouterHonoServer({ runtime: "bun"} ), // add this
reactRouter(),
tsconfigPaths()
],
});
Cloudflare Workers
Tip
Check this example to see how to use it.
Important
You need to add the cloudflareDevProxy
plugin to use the Cloudflare Workers runtime on dev.
// vite.config.ts
import { reactRouter } from "@react-router/dev/vite";
import { cloudflareDevProxy } from "@react-router/dev/vite/cloudflare"; // add this
import { reactRouterHonoServer } from "react-router-hono-server/dev"; // add this
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
export default defineConfig({
plugins: [
cloudflareDevProxy(),
reactRouterHonoServer({ runtime: "cloudflare"} ), // add this
reactRouter(),
tsconfigPaths()
],
});
Full Changelog: v2.1.0...v2.1.2
v2.1.0
What's Changed
Bun
Tip
Check this example to see how to use it.
// vite.config.ts
import { reactRouter } from "@react-router/dev/vite";
import { reactRouterHonoServer } from "react-router-hono-server/dev"; // add this
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
export default defineConfig({
plugins: [
reactRouterHonoServer({ runtime: "bun"} ), // add this
reactRouter(),
tsconfigPaths()
],
});
Cloudflare Workers
Tip
Check this example to see how to use it.
Important
You need to add the cloudflareDevProxy
plugin to use the Cloudflare Workers runtime on dev.
// vite.config.ts
import { reactRouter } from "@react-router/dev/vite";
import { cloudflareDevProxy } from "@react-router/dev/vite/cloudflare"; // add this
import { reactRouterHonoServer } from "react-router-hono-server/dev"; // add this
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
export default defineConfig({
plugins: [
cloudflareDevProxy(),
reactRouterHonoServer({ runtime: "cloudflare"} ), // add this
reactRouter(),
tsconfigPaths()
],
});
Full Changelog: v2.0.0...v2.1.0
v2.0.0
What's Changed
- Support for react-router v7 by @AlemTuzlak in #10
- V2 - React Router v7 by @rphlmr in #18
Important
This new version is only compatible with React Router v7
You can still use the v1 with @remix-run. Previous docs
Migration guide from v1 here
It's now a Vite Plugin 🥳
Install the following npm package.
npm install react-router-hono-server@latest
Easy mode
In your vite.config.ts
, add the reactRouterHonoServer
plugin.
import { reactRouter } from "@react-router/dev/vite";
import { reactRouterHonoServer } from "react-router-hono-server/dev"; // add this
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
export default defineConfig({
plugins: [
reactRouterHonoServer(), // add this
reactRouter(),
tsconfigPaths()
],
});
That's all!
How it works
This helper works differently depending on the environment.
In development, it uses @hono/vite-dev-server and loads your server and React Router app with import('virtual:react-router/server-build')
.
It can be configured in vite.config.ts
.
When building for production, the Hono server is compiled as build/server/index.js
and imports your React Router app from assets/server-build-[hash].js
.
New Contributors
- @AlemTuzlak made their first contribution in #10
Full Changelog: v1.2.0...v2.0.0