From fb0e26b66c3c5f74c1c66c6dd7916b4b23bca15e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcholas=20Andr=C3=A9?= Date: Sun, 23 Jun 2024 15:22:28 -0300 Subject: [PATCH] feat: exploring multi site support in app router --- packages/next/src/middlewares/appMidleware.ts | 30 ++++++++++++++----- packages/next/src/rsc/config.ts | 18 +++++++++++ packages/next/src/rsc/index.ts | 1 + projects/wp-nextjs-app/src/app/middleware.ts | 19 ++++++++++++ 4 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 packages/next/src/rsc/config.ts create mode 100644 projects/wp-nextjs-app/src/app/middleware.ts diff --git a/packages/next/src/middlewares/appMidleware.ts b/packages/next/src/middlewares/appMidleware.ts index 75aa189d4..799aee27c 100644 --- a/packages/next/src/middlewares/appMidleware.ts +++ b/packages/next/src/middlewares/appMidleware.ts @@ -1,6 +1,6 @@ import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; -import { fetchRedirect, getHeadlessConfig, getSiteByHost } from '@headstartwp/core/utils'; +import { fetchRedirect, getHeadstartWPConfig, getSiteByHost } from '@headstartwp/core/utils'; const ALLOWED_STATIC_PATHS = /^\/.*\.(ico|png|jpg|jpeg)$/g; @@ -12,16 +12,25 @@ function isInternalRequest(req: NextRequest) { return req.nextUrl.pathname.startsWith('/_next'); } -export async function AppMiddleware(req: NextRequest) { +type AppMidlewareOptions = { + appRouter: boolean; +}; + +export async function AppMiddleware( + req: NextRequest, + options: AppMidlewareOptions = { appRouter: false }, +) { + const response = NextResponse.next(); + if (isStaticAssetRequest(req) || isInternalRequest(req)) { - return NextResponse.next(); + return response; } const hostname = req.headers.get('host') || ''; const site = getSiteByHost(hostname, req.nextUrl.locale); const isMultisiteRequest = site !== null && typeof site.sourceUrl !== 'undefined'; - const { redirectStrategy, sourceUrl } = isMultisiteRequest ? site : getHeadlessConfig(); + const { redirectStrategy, sourceUrl } = isMultisiteRequest ? site : getHeadstartWPConfig(); if (!sourceUrl) { throw new Error('Site not found.'); @@ -42,11 +51,18 @@ export async function AppMiddleware(req: NextRequest) { } if (isMultisiteRequest) { - const url = req.nextUrl; const hostname = req.headers.get('host') || ''; - url.pathname = `/_sites/${hostname}${url.pathname}`; + response.headers.set('x-headstartwp-site', hostname); + const url = req.nextUrl; + + if (options.appRouter) { + url.pathname = `/${hostname}${url.pathname}`; + } else { + url.pathname = `/_sites/${hostname}${url.pathname}`; + } + return NextResponse.rewrite(url); } - return NextResponse.next(); + return response; } diff --git a/packages/next/src/rsc/config.ts b/packages/next/src/rsc/config.ts new file mode 100644 index 000000000..e982bb4eb --- /dev/null +++ b/packages/next/src/rsc/config.ts @@ -0,0 +1,18 @@ +import { getHeadstartWPConfig, getSiteByHost } from '@headstartwp/core'; +import { headers } from 'next/headers'; + +/** + * How to make this work in edge runtimes? + */ +export async function loadHeadstartWPConfig() { + const config = getHeadstartWPConfig(); + const headersList = headers(); + + const site = headersList.get('x-headstartwp-site'); + + if (site) { + return getSiteByHost(site); + } + + return config; +} diff --git a/packages/next/src/rsc/index.ts b/packages/next/src/rsc/index.ts index 3720fdf1e..9b2ecf4a0 100644 --- a/packages/next/src/rsc/index.ts +++ b/packages/next/src/rsc/index.ts @@ -1,2 +1,3 @@ export * from './data'; export * from './type'; +export * from './config'; diff --git a/projects/wp-nextjs-app/src/app/middleware.ts b/projects/wp-nextjs-app/src/app/middleware.ts new file mode 100644 index 000000000..1fb773757 --- /dev/null +++ b/projects/wp-nextjs-app/src/app/middleware.ts @@ -0,0 +1,19 @@ +import { AppMiddleware } from '@headstartwp/next/middlewares'; +import { NextRequest } from 'next/server'; + +export const config = { + matcher: [ + /* + * Match all paths except for: + * 1. /api routes + * 2. /_next (Next.js internals) + * 3. /fonts (inside /public) + * 4. all root files inside /public (e.g. /favicon.ico) + */ + '/((?!api|cache-healthcheck|_next|fonts[\\w-]+\\.\\w+).*)', + ], +}; + +export async function middleware(req: NextRequest) { + return AppMiddleware(req, { appRouter: true }); +}