Skip to content

Commit 3603522

Browse files
committed
feat: add middleware
1 parent 30357cd commit 3603522

File tree

6 files changed

+30
-10
lines changed

6 files changed

+30
-10
lines changed

app/entry.server.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,16 @@ import { createInstance } from "i18next"
44
import { isbot } from "isbot"
55
import { renderToPipeableStream } from "react-dom/server"
66
import { I18nextProvider, initReactI18next } from "react-i18next"
7-
import { type AppLoadContext, type EntryContext, type HandleDataRequestFunction, ServerRouter } from "react-router"
7+
import {
8+
type EntryContext,
9+
type HandleDataRequestFunction,
10+
type RouterContextProvider,
11+
ServerRouter,
12+
} from "react-router"
813
import i18n from "./localization/i18n" // your i18n configuration file
914
import i18nextOpts from "./localization/i18n.server"
1015
import { resources } from "./localization/resource"
16+
import { globalAppContext } from "./server/context"
1117

1218
// Reject all pending promises from handler functions after 10 seconds
1319
export const streamTimeout = 10000
@@ -17,11 +23,12 @@ export default async function handleRequest(
1723
responseStatusCode: number,
1824
responseHeaders: Headers,
1925
context: EntryContext,
20-
appContext: AppLoadContext
26+
appContext: RouterContextProvider
2127
) {
2228
const callbackName = isbot(request.headers.get("user-agent")) ? "onAllReady" : "onShellReady"
2329
const instance = createInstance()
24-
const lng = appContext.lang
30+
const ctx = appContext.get(globalAppContext)
31+
const lng = ctx.lang
2532
const ns = i18nextOpts.getRouteNamespaces(context)
2633

2734
await instance
@@ -48,7 +55,7 @@ export default async function handleRequest(
4855

4956
resolve(
5057
// @ts-expect-error - We purposely do not define the body as existent so it's not used inside loaders as it's injected there as well
51-
appContext.body(stream, {
58+
ctx.body(stream, {
5259
headers: responseHeaders,
5360
status: didError ? 500 : responseStatusCode,
5461
})

app/root.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ import { isRouteErrorResponse, Links, Meta, Outlet, Scripts, ScrollRestoration,
44
import { useChangeLanguage } from "remix-i18next/react"
55
import type { Route } from "./+types/root"
66
import { LanguageSwitcher } from "./library/language-switcher"
7+
import { globalAppContext } from "./server/context"
78
import { ClientHintCheck, getHints } from "./services/client-hints"
89
import tailwindcss from "./tailwind.css?url"
910

1011
export async function loader({ context, request }: Route.LoaderArgs) {
11-
const { lang, clientEnv } = context
12+
const { lang, clientEnv } = context.get(globalAppContext)
1213
const hints = getHints(request)
1314
return { lang, clientEnv, hints }
1415
}

app/routes/resource.locales.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { cacheHeader } from "pretty-cache-header"
22
import { z } from "zod/v4"
33
import { type Language, type Namespace, resources } from "~/localization/resource"
4+
import { globalAppContext } from "~/server/context"
45
import type { Route } from "./+types/resource.locales"
56

67
export async function loader({ request, context }: Route.LoaderArgs) {
7-
const { isProductionDeployment } = context
8+
const { isProductionDeployment } = context.get(globalAppContext)
89
const url = new URL(request.url)
910

1011
const lng = z.enum(Object.keys(resources) as Language[]).parse(url.searchParams.get("lng"))

app/routes/robots[.]txt.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { generateRobotsTxt } from "@forge42/seo-tools/robots"
2-
2+
import { globalAppContext } from "~/server/context"
33
import { createDomain } from "~/utils/http"
44
import type { Route } from "./+types/robots[.]txt"
55

66
export async function loader({ request, context }: Route.LoaderArgs) {
7-
const { isProductionDeployment } = context
7+
const { isProductionDeployment } = context.get(globalAppContext)
88
const domain = createDomain(request)
99
const robotsTxt = generateRobotsTxt([
1010
{

app/server/context.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import type { Context } from "hono"
2+
import { createContext, RouterContextProvider } from "react-router"
23
import { i18next } from "remix-hono/i18next"
34
import { getClientEnv, getServerEnv } from "~/env.server"
45

5-
export const getLoadContext = async (c: Context) => {
6+
export const globalAppContext = createContext<LoadContext>()
7+
8+
export const getAppContext = async (c: Context) => {
69
// get the locale from the context
710
const locale = i18next.getLocale(c)
811
// get t function for the default namespace
@@ -21,7 +24,14 @@ export const getLoadContext = async (c: Context) => {
2124
}
2225
}
2326

24-
interface LoadContext extends Awaited<ReturnType<typeof getLoadContext>> {}
27+
export const getLoadContext = async (c: Context) => {
28+
const ctx = new RouterContextProvider()
29+
const globalCtx = await getAppContext(c)
30+
ctx.set(globalAppContext, globalCtx)
31+
return ctx
32+
}
33+
34+
interface LoadContext extends Awaited<ReturnType<typeof getAppContext>> {}
2535

2636
/**
2737
* Declare our loaders and actions context type

react-router.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ export default {
55
unstable_viteEnvironmentApi: true,
66
unstable_splitRouteModules: true,
77
unstable_optimizeDeps: true,
8+
v8_middleware: true,
89
},
910
} satisfies Config

0 commit comments

Comments
 (0)