diff --git a/netlify-server.ts b/netlify-server.ts new file mode 100644 index 00000000..45e7d928 --- /dev/null +++ b/netlify-server.ts @@ -0,0 +1,62 @@ +import type { AppLoadContext, ServerBuild } from '@netlify/remix-runtime' +import { createRequestHandler as createRemixRequestHandler } from '@netlify/remix-runtime' +import type { Context } from '@netlify/edge-functions' + +type LoadContext = AppLoadContext & Context + +/** + * A function that returns the value to use as `context` in route `loader` and + * `action` functions. + * + * You can think of this as an escape hatch that allows you to pass + * environment/platform-specific values through to your loader/action. + */ +export type GetLoadContextFunction = (request: Request, context: Context) => Promise | LoadContext + +export type RequestHandler = (request: Request, context: LoadContext) => Promise + +export function createRequestHandler({ + build, + mode, + getLoadContext, +}: { + build: ServerBuild + mode?: string + getLoadContext?: GetLoadContextFunction +}): RequestHandler { + const remixHandler = createRemixRequestHandler(build, mode) + + const assetPath = build.assets.url.split('/').slice(0, -1).join('/') + + return async (request: Request, context: LoadContext): Promise => { + const { pathname } = new URL(request.url) + // Skip the handler for static files + if (pathname.startsWith(`${assetPath}/`)) { + console.log('Skipping Remix handler for static file', pathname) + return + } + try { + const loadContext = (await getLoadContext?.(request, context)) || context + + const response = await remixHandler(request, loadContext) + + // A useful header for debugging + response.headers.set('x-nf-runtime', 'Edge') + + if (response.status === 404) { + // Check if there is a matching static file + const originResponse = await context.next({ + sendConditionalRequest: true, + }) + if (originResponse.status !== 404) { + return originResponse + } + } + return response + } catch (error: unknown) { + console.error(error) + + return new Response('Internal Error', { status: 500 }) + } + } +} diff --git a/package.json b/package.json index d0d36ab7..d77cf5c5 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@actions/github": "^5.1.1", "@babel/core": "^7.21.0", "@babel/preset-react": "^7.18.6", + "@netlify/edge-functions": "^2.0.0", "@netlify/functions": "^1.4.0", "@netlify/remix-edge-adapter": "^1.0.0", "@remix-run/dev": "^1.13.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bf534b36..8cfb85d7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,6 +6,7 @@ specifiers: '@actions/github': ^5.1.1 '@babel/core': ^7.21.0 '@babel/preset-react': ^7.18.6 + '@netlify/edge-functions': ^2.0.0 '@netlify/functions': ^1.4.0 '@netlify/remix-edge-adapter': ^1.0.0 '@remix-run/dev': ^1.13.0 @@ -43,6 +44,7 @@ dependencies: '@actions/github': 5.1.1 '@babel/core': 7.21.0 '@babel/preset-react': 7.18.6_@babel+core@7.21.0 + '@netlify/edge-functions': 2.0.0 '@netlify/functions': 1.4.0 '@netlify/remix-edge-adapter': 1.0.0 '@remix-run/dev': 1.13.0_@remix-run+serve@1.13.0 @@ -1386,6 +1388,17 @@ packages: postcss-selector-parser: 6.0.11 dev: true + /@deno/shim-deno-test/0.3.3: + resolution: {integrity: sha512-Ge0Tnl7zZY0VvEfgsyLhjid8DzI1d0La0dgm+3m0/A8gZXgp5xwlyIyue5e4SCUuVB/3AH/0lun9LcJhhTwmbg==} + dev: false + + /@deno/shim-deno/0.10.0: + resolution: {integrity: sha512-E7rQ0Hk33V45xQXKEnCxizdSP5C+hhqw1H3xWXsct3kYFWgG93B5gN3LKlyvcxbckt8d67jVa6s+y5duRYawvg==} + dependencies: + '@deno/shim-deno-test': 0.3.3 + which: 2.0.2 + dev: false + /@emotion/hash/0.9.0: resolution: {integrity: sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==} dev: false @@ -1719,6 +1732,13 @@ packages: '@jridgewell/resolve-uri': 3.1.0 '@jridgewell/sourcemap-codec': 1.4.14 + /@netlify/edge-functions/2.0.0: + resolution: {integrity: sha512-mRVGnPNA4YayDLPwnO1ZrcWwBODPj5BQPbx3/FUlQtZ5ow2D+PjMPQr8IcFm0HfMJQgtHZS39p9VS6PRSi1ePw==} + engines: {node: ^14.16.0 || >=16.0.0} + dependencies: + '@deno/shim-deno': 0.10.0 + dev: false + /@netlify/functions/1.4.0: resolution: {integrity: sha512-gy7ULTIRroc2/jyFVGx1djCmmBMVisIwrvkqggq5B6iDcInRSy2Tpkm+V5C63hKJVkNRskKWtLQKm9ecCaQTjA==} engines: {node: '>=8.3.0'} diff --git a/server.ts b/server.ts index 1b172209..87c1eedb 100644 --- a/server.ts +++ b/server.ts @@ -1,6 +1,7 @@ // Import path interpreted by the Remix compiler import * as build from "@remix-run/dev/server-build"; -import { createRequestHandler } from "@netlify/remix-edge-adapter"; +// import { createRequestHandler } from "@netlify/remix-edge-adapter"; +import { createRequestHandler } from "./netlify-server"; export default createRequestHandler({ build,