From 613e2119766f18803fbbc52fd0573ffc0e1404d3 Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Tue, 21 Feb 2023 15:21:21 -0500 Subject: [PATCH 01/20] remove static folder --- static/fonts.css | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 static/fonts.css diff --git a/static/fonts.css b/static/fonts.css deleted file mode 100644 index e0a145a6..00000000 --- a/static/fonts.css +++ /dev/null @@ -1,16 +0,0 @@ - /* Fonts */ - @font-face { - font-family: 'Fira Mono'; - font-weight: 400; - font-style: normal; - src: url('../src/fonts/fira_mono-regular-webfont.woff2') format('woff2'), - url('../src/fonts/fira_mono-regular-webfont.woff') format('woff'); - font-display: swap; - } - @font-face { - font-family: 'Fira Mono'; - font-weight: 400; - font-style: italic; - src: url('../src/fonts/fira_mono-regular_italic-webfont.woff2') format('woff2'), url('../src/fonts/fira_mono-regular_italic-webfont.woff') format('woff'); - font-display: swap; - } From a9fd7d5d1362ea3f379f051e8d8607bf92a243a8 Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Tue, 21 Feb 2023 15:37:44 -0500 Subject: [PATCH 02/20] Netlify Edge Functions --- package.json | 1 + pnpm-lock.yaml | 14 ++++++++++++++ remix.config.js | 4 +++- server.js | 51 +++++++++---------------------------------------- 4 files changed, 27 insertions(+), 43 deletions(-) diff --git a/package.json b/package.json index 6c34191d..0c450f0b 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@babel/core": "^7.21.0", "@babel/preset-react": "^7.18.6", "@netlify/functions": "^1.4.0", + "@netlify/remix-edge-adapter": "^1.0.0", "@remix-run/dev": "^1.13.0", "@remix-run/netlify": "^1.13.0", "@remix-run/node": "^1.13.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 20cc8860..ba862d2f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,6 +7,7 @@ specifiers: '@babel/core': ^7.21.0 '@babel/preset-react': ^7.18.6 '@netlify/functions': ^1.4.0 + '@netlify/remix-edge-adapter': ^1.0.0 '@remix-run/dev': ^1.13.0 '@remix-run/netlify': ^1.13.0 '@remix-run/node': ^1.13.0 @@ -42,6 +43,7 @@ dependencies: '@babel/core': 7.21.0 '@babel/preset-react': 7.18.6_@babel+core@7.21.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 '@remix-run/netlify': 1.13.0_@netlify+functions@1.4.0 '@remix-run/node': 1.13.0 @@ -1722,6 +1724,18 @@ packages: is-promise: 4.0.0 dev: false + /@netlify/remix-edge-adapter/1.0.0: + resolution: {integrity: sha512-NdTDRW8X/Iyh/ywHcf5H7HUkLoc/k2oxxOMIO5/rm0LHMN2bGFhbOxMBfi0PtFsa/Jn+efbNTkCM15JXoITzSw==} + dependencies: + '@netlify/remix-runtime': 1.0.0 + dev: false + + /@netlify/remix-runtime/1.0.0: + resolution: {integrity: sha512-w1nLlMABrW5uJoQc3eADWZ4wgnRqcqpNOQ+ZMQnoXSwukUGGN6JwGs3/BP+f/8F4CCy7sakbbF+akBmyKIKciQ==} + dependencies: + '@remix-run/server-runtime': 1.13.0 + dev: false + /@nicolo-ribaudo/eslint-scope-5-internals/5.1.1-v1: resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} dependencies: diff --git a/remix.config.js b/remix.config.js index 2063012d..aac8e782 100644 --- a/remix.config.js +++ b/remix.config.js @@ -1,5 +1,7 @@ +const { config } = require("@netlify/remix-edge-adapter"); /** @type {import('@remix-run/dev').AppConfig} */ module.exports = { + ...config, appDirectory: "src", future: { unstable_postcss: true, @@ -9,5 +11,5 @@ module.exports = { process.env.NETLIFY || process.env.NETLIFY_LOCAL ? "./server.js" : undefined, - serverBuildPath: ".netlify/functions-internal/server.js", + // serverBuildPath: ".netlify/functions-internal/server.js", }; diff --git a/server.js b/server.js index b981b1a2..1b172209 100644 --- a/server.js +++ b/server.js @@ -1,47 +1,14 @@ -import { createRequestHandler } from "@remix-run/netlify"; +// Import path interpreted by the Remix compiler import * as build from "@remix-run/dev/server-build"; +import { createRequestHandler } from "@netlify/remix-edge-adapter"; -/* - * Returns a context object with at most 3 keys: - * - `netlifyGraphToken`: raw authentication token to use with Netlify Graph - * - `clientNetlifyGraphAccessToken`: For use with JWTs generated by - * `netlify-graph-auth`. - * - `netlifyGraphSignature`: a signature for subscription events. Will be - * present if a secret is set. - */ -function getLoadContext(event, context) { - let rawAuthorizationString; - let netlifyGraphToken; - - if (event.authlifyToken != null) { - netlifyGraphToken = event.authlifyToken; - } - - const authHeader = event.headers["authorization"]; - const graphSignatureHeader = event.headers["x-netlify-graph-signature"]; - - if (authHeader != null && /Bearer /gi.test(authHeader)) { - rawAuthorizationString = authHeader.split(" ")[1]; - } - - const loadContext = { - clientNetlifyGraphAccessToken: rawAuthorizationString, - netlifyGraphToken: netlifyGraphToken, - netlifyGraphSignature: graphSignatureHeader, - }; - - // Remove keys with undefined values - Object.keys(loadContext).forEach((key) => { - if (loadContext[key] == null) { - delete loadContext[key]; - } - }); - - return loadContext; -} - -export const handler = createRequestHandler({ +export default createRequestHandler({ build, - getLoadContext, + // process.env.NODE_ENV is provided by Remix at compile time mode: process.env.NODE_ENV, }); + +export const config = { + cache: "manual", + path: "/*", +}; From 72c7df8a662ddd810f1f7368da78cbd948dc0b74 Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Tue, 21 Feb 2023 16:11:11 -0500 Subject: [PATCH 03/20] WIP --- package.json | 1 + pnpm-lock.yaml | 7 +++ src/entry.server.tsx | 110 +++++++++++++++++++------------------------ 3 files changed, 56 insertions(+), 62 deletions(-) diff --git a/package.json b/package.json index 0c450f0b..d0d36ab7 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "@types/react": "^18.0.28", "@types/react-dom": "^18.0.11", "country-emoji": "^1.5.6", + "isbot": "^3.6.6", "joi": "^17.8.1", "normalize.css": "^8.0.1", "prop-types": "^15.8.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ba862d2f..bf534b36 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -22,6 +22,7 @@ specifiers: eslint: ^8.34.0 eslint-config-wesbos: ^3.2.3 husky: ^8.0.3 + isbot: ^3.6.6 joi: ^17.8.1 lint-staged: ^13.1.2 normalize.css: ^8.0.1 @@ -54,6 +55,7 @@ dependencies: '@types/react': 18.0.28 '@types/react-dom': 18.0.11 country-emoji: 1.5.6 + isbot: 3.6.6 joi: 17.8.1 normalize.css: 8.0.1 prop-types: 15.8.1 @@ -4895,6 +4897,11 @@ packages: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} dev: true + /isbot/3.6.6: + resolution: {integrity: sha512-98aGl1Spbx1led422YFrusDJ4ZutSNOymb2avZ2V4BCCjF3MqAF2k+J2zoaLYahubaFkb+3UyvbVDVlk/Ngrew==} + engines: {node: '>=12'} + dev: false + /isexe/2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} diff --git a/src/entry.server.tsx b/src/entry.server.tsx index 253d2c5b..daca8b3d 100644 --- a/src/entry.server.tsx +++ b/src/entry.server.tsx @@ -1,84 +1,70 @@ -import { PassThrough } from 'stream'; import type { EntryContext } from '@remix-run/node'; -import { Response } from '@remix-run/node'; import { RemixServer } from '@remix-run/react'; -import { renderToPipeableStream } from 'react-dom/server'; +import { renderToReadableStream } from 'react-dom/server'; const ABORT_DELAY = 5000; type CachedResponse = { - html:string; + html: string; date: Date; } const cache = new Map(); - -export default function handleRequest( +export default async function handleRequest( request: Request, responseStatusCode: number, responseHeaders: Headers, remixContext: EntryContext ) { + console.log('😆'); console.log(request.url); - // check if we have a cached response in memory - const cachedResponse = cache.get(request.url); - if (cachedResponse) { - console.log('Serving from cache', request.url); - // if we have a cached response, check if it's less than 5 seconds old - const now = new Date(); - const diff = now.getTime() - cachedResponse.date.getTime(); - if (true || diff < 5000) { - // if it's less than 5 seconds old, return the cached response - responseHeaders.set('Content-Type', 'text/html'); - return new Response(cachedResponse.html, { - headers: responseHeaders, - status: responseStatusCode, - }); - } - } + // // check if we have a cached response in memory + // const cachedResponse = cache.get(request.url); + // if (cachedResponse) { + // console.log('Serving from cache', request.url); + // // if we have a cached response, check if it's less than 5 seconds old + // const now = new Date(); + // const diff = now.getTime() - cachedResponse.date.getTime(); + // if (true || diff < 5000) { + // // if it's less than 5 seconds old, return the cached response + // responseHeaders.set('Content-Type', 'text/html'); + // return new Response(cachedResponse.html, { + // headers: responseHeaders, + // status: responseStatusCode, + // }); + // } + // } - return new Promise((resolve, reject) => { - let didError = false; - const chunks: Uint8Array[] = []; + let didError = false; + const chunks: Uint8Array[] = []; - const { pipe, abort } = renderToPipeableStream( - , - { - onShellReady: () => { - const body = new PassThrough(); - - body - .on('data', (data) => { - chunks.push(data); - }) - .on('end', () => { - const html = Buffer.concat(chunks).toString('utf8'); - cache.set(request.url, { html: html.replace('Rendered Fresh', `Served from Cache ${new Date().toString()}`), date: new Date() }); - }) - - responseHeaders.set('Content-Type', 'text/html'); - - resolve( - new Response(body, { - headers: responseHeaders, - status: didError ? 500 : responseStatusCode, - }) - ); - - pipe(body); - }, - onShellError: (err: unknown) => { - reject(err); - }, - onError: (error: unknown) => { - didError = true; - - console.error(error); - } + const body = await renderToReadableStream( + , + { + onError: (error: unknown) => { + didError = true; + console.error(error); } - ); + } + ); + console.log(body); + + // body + // .on('data', (data) => { + // console.log('data', data); + // chunks.push(data); + // }) + // .on('end', () => { + // const html = Buffer.concat(chunks).toString('utf8'); + // cache.set(request.url, { html: html.replace('Rendered Fresh', `Served from Cache ${new Date().toString()}`), date: new Date() }); + // }) + + const headers = new Headers(responseHeaders); + headers.set("Content-Type", "text/html"); + new Response(body, { + headers, + status: didError ? 500 : responseStatusCode, + }) - setTimeout(abort, ABORT_DELAY); - }); } From acfef2b3f7d89bdc037995e8dafe7f845494e628 Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Tue, 21 Feb 2023 16:29:26 -0500 Subject: [PATCH 04/20] working --- netlify.toml | 1 + src/entry.server.tsx | 7 ++----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/netlify.toml b/netlify.toml index ec357029..c4d74854 100644 --- a/netlify.toml +++ b/netlify.toml @@ -6,6 +6,7 @@ [dev] command = "remix watch" port = 3000 + autoLaunch = false [[redirects]] from = "/*" diff --git a/src/entry.server.tsx b/src/entry.server.tsx index daca8b3d..a87f7eeb 100644 --- a/src/entry.server.tsx +++ b/src/entry.server.tsx @@ -16,8 +16,6 @@ export default async function handleRequest( responseHeaders: Headers, remixContext: EntryContext ) { - console.log('😆'); - console.log(request.url); // // check if we have a cached response in memory // const cachedResponse = cache.get(request.url); // if (cachedResponse) { @@ -48,9 +46,8 @@ export default async function handleRequest( } } ); - console.log(body); - // body + // body.pip // .on('data', (data) => { // console.log('data', data); // chunks.push(data); @@ -62,7 +59,7 @@ export default async function handleRequest( const headers = new Headers(responseHeaders); headers.set("Content-Type", "text/html"); - new Response(body, { + return new Response(body, { headers, status: didError ? 500 : responseStatusCode, }) From 9c2e3c592659b76f46506b2bf6e663e9c768356a Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Tue, 21 Feb 2023 17:05:08 -0500 Subject: [PATCH 05/20] tee streams --- src/entry.server.tsx | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/entry.server.tsx b/src/entry.server.tsx index a87f7eeb..94b1acf9 100644 --- a/src/entry.server.tsx +++ b/src/entry.server.tsx @@ -4,6 +4,20 @@ import { renderToReadableStream } from 'react-dom/server'; const ABORT_DELAY = 5000; +export async function streamToText(stream: ReadableStream): Promise { + let result = ''; + const reader = stream.pipeThrough(new TextDecoderStream()).getReader(); + while (true) { // eslint-disable-line no-constant-condition + const { done, value } = await reader.read(); + if (done) { + break; + } + + result += value; + } + return result; +} + type CachedResponse = { html: string; date: Date; @@ -33,7 +47,6 @@ export default async function handleRequest( // } // } - let didError = false; const chunks: Uint8Array[] = []; @@ -47,21 +60,17 @@ export default async function handleRequest( } ); - // body.pip - // .on('data', (data) => { - // console.log('data', data); - // chunks.push(data); - // }) - // .on('end', () => { - // const html = Buffer.concat(chunks).toString('utf8'); - // cache.set(request.url, { html: html.replace('Rendered Fresh', `Served from Cache ${new Date().toString()}`), date: new Date() }); - // }) + const [toReponse, toCache] = body.tee(); + + streamToText(toCache).then(html => { + console.log('I have the HTML!', html.length); + }); const headers = new Headers(responseHeaders); headers.set("Content-Type", "text/html"); - return new Response(body, { + const response = new Response(toReponse, { headers, status: didError ? 500 : responseStatusCode, - }) - + }); + return response; } From 585e6088fa9cb8d7b44695b3d7357be1ab1ba95d Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Wed, 22 Feb 2023 13:47:13 -0500 Subject: [PATCH 06/20] fix build --- netlify.toml | 2 +- src/entry.server.tsx | 39 ++++++++++++++++++++++----------------- src/util/stats.ts | 12 +++++++----- 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/netlify.toml b/netlify.toml index c4d74854..0aece3d7 100644 --- a/netlify.toml +++ b/netlify.toml @@ -10,7 +10,7 @@ [[redirects]] from = "/*" - to = "/.netlify/functions/server" + to = "/.netlify/edge-functions/server" status = 200 [[headers]] diff --git a/src/entry.server.tsx b/src/entry.server.tsx index 94b1acf9..6630113c 100644 --- a/src/entry.server.tsx +++ b/src/entry.server.tsx @@ -30,22 +30,22 @@ export default async function handleRequest( responseHeaders: Headers, remixContext: EntryContext ) { - // // check if we have a cached response in memory - // const cachedResponse = cache.get(request.url); - // if (cachedResponse) { - // console.log('Serving from cache', request.url); - // // if we have a cached response, check if it's less than 5 seconds old - // const now = new Date(); - // const diff = now.getTime() - cachedResponse.date.getTime(); - // if (true || diff < 5000) { - // // if it's less than 5 seconds old, return the cached response - // responseHeaders.set('Content-Type', 'text/html'); - // return new Response(cachedResponse.html, { - // headers: responseHeaders, - // status: responseStatusCode, - // }); - // } - // } + // check if we have a cached response in memory + const cachedResponse = cache.get(request.url); + if (cachedResponse) { + console.log('Serving from cache', request.url); + // if we have a cached response, check if it's less than 5 seconds old + const now = new Date(); + const diff = now.getTime() - cachedResponse.date.getTime(); + if (true || diff < 5000) { + // if it's less than 5 seconds old, return the cached response + responseHeaders.set('Content-Type', 'text/html'); + return new Response(cachedResponse.html, { + headers: responseHeaders, + status: responseStatusCode, + }); + } + } let didError = false; const chunks: Uint8Array[] = []; @@ -60,10 +60,15 @@ export default async function handleRequest( } ); + // tee the stream so we can cache it and send it to the client const [toReponse, toCache] = body.tee(); streamToText(toCache).then(html => { - console.log('I have the HTML!', html.length); + console.log('Caching', request.url); + cache.set(request.url, { + html: html.replace('Rendered Fresh',`Rendered from cache ${new Date().toISOString()}`), + date: new Date(), + }); }); const headers = new Headers(responseHeaders); diff --git a/src/util/stats.ts b/src/util/stats.ts index 92bcb14c..b0f040c3 100644 --- a/src/util/stats.ts +++ b/src/util/stats.ts @@ -64,7 +64,6 @@ export function tags() { const counts = allTags.reduce(countInstances, {}); // sort and filter for any tags that only have 1 const tags = Object.entries(counts) - .sort(([, countA], [, countB]) => countB - countA) // Only show the tag if this topic has 3 or more people in it .filter(([, count]) => count >= 3) .map(([name, count]) => ({ name, count })); @@ -85,8 +84,11 @@ export function tags() { delete lowercaseTagMap[normalizedName]; } return acc; - }, []); - + }, []) + // Sort by name first + .sort((a, b) => b.name.toLowerCase() > a.name.toLowerCase()) + // Sort by count + .sort((a, b) => b.count - a.count); return [{ name: 'all', count: people.length }, ...normalizedTags]; } @@ -116,12 +118,12 @@ const normalizedTagMap = tags().reduce((acc, tag) => { }, {}); export function getPeople(tag?: string) { - return people + return [...people] .sort(() => Math.random() - 0.5) .map((person) => { const normalizedPerson = { ...person, - // Clean out people that added basically the same tags twice + // Clean out people that added basically the same tags twice tags: unique( person.tags.map((tag) => normalizedTagMap[normalizeTag(tag)] || tag) ), From b2256ab0c27d831e723bfee437517b7ca622374a Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Wed, 22 Feb 2023 13:54:19 -0500 Subject: [PATCH 07/20] remove functions --- netlify.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/netlify.toml b/netlify.toml index 0aece3d7..f6e30b53 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,6 +1,5 @@ [build] command = "remix build" - functions = "netlify/functions" publish = "public" [dev] From 3b51180cae7cf6c92f853299aac7736f3efed99b Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Wed, 22 Feb 2023 14:36:48 -0500 Subject: [PATCH 08/20] try build --- netlify.toml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/netlify.toml b/netlify.toml index f6e30b53..050601c4 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,16 +1,17 @@ [build] command = "remix build" - publish = "public" + publish = "build" [dev] command = "remix watch" port = 3000 + # targetPort = 3000 autoLaunch = false -[[redirects]] - from = "/*" - to = "/.netlify/edge-functions/server" - status = 200 +# [[redirects]] +# from = "/*" +# to = "/.netlify/edge-functions/server" +# status = 200 [[headers]] for = "/build/*" From e5bf005059aa9a00b1ef4fe7d99732ccfc75ec69 Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Wed, 22 Feb 2023 14:38:26 -0500 Subject: [PATCH 09/20] nope --- netlify.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/netlify.toml b/netlify.toml index 050601c4..fa5ce129 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,11 +1,10 @@ [build] command = "remix build" - publish = "build" + publish = "public" [dev] command = "remix watch" port = 3000 - # targetPort = 3000 autoLaunch = false # [[redirects]] From a44634615bbc4e0dd67e70ab15642cc7e8a9af1b Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Wed, 22 Feb 2023 14:51:30 -0500 Subject: [PATCH 10/20] maybe --- netlify.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netlify.toml b/netlify.toml index fa5ce129..c919b5b1 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,6 +1,6 @@ [build] command = "remix build" - publish = "public" + # publish = "public" [dev] command = "remix watch" From 5134949685abe0297dcd2da7319a845893708407 Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Wed, 22 Feb 2023 15:03:25 -0500 Subject: [PATCH 11/20] crazy pills --- netlify.toml | 7 +------ remix.config.js | 1 + 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/netlify.toml b/netlify.toml index c919b5b1..8764ef9a 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,17 +1,12 @@ [build] command = "remix build" - # publish = "public" + publish = "public" [dev] command = "remix watch" port = 3000 autoLaunch = false -# [[redirects]] -# from = "/*" -# to = "/.netlify/edge-functions/server" -# status = 200 - [[headers]] for = "/build/*" [headers.values] diff --git a/remix.config.js b/remix.config.js index aac8e782..de4c9dcc 100644 --- a/remix.config.js +++ b/remix.config.js @@ -6,6 +6,7 @@ module.exports = { future: { unstable_postcss: true, }, + assetsBuildDirectory: "publicxxxx/baller", ignoredRouteFiles: ["**/.*"], server: process.env.NETLIFY || process.env.NETLIFY_LOCAL From 5c732ad368fdbca5fbaca956b3c04305506fbe9d Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Wed, 22 Feb 2023 15:04:29 -0500 Subject: [PATCH 12/20] crazy pills --- remix.config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/remix.config.js b/remix.config.js index de4c9dcc..aac8e782 100644 --- a/remix.config.js +++ b/remix.config.js @@ -6,7 +6,6 @@ module.exports = { future: { unstable_postcss: true, }, - assetsBuildDirectory: "publicxxxx/baller", ignoredRouteFiles: ["**/.*"], server: process.env.NETLIFY || process.env.NETLIFY_LOCAL From 82207220b8fe1bb445de47b1c93bc6dee304a444 Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Wed, 22 Feb 2023 15:14:40 -0500 Subject: [PATCH 13/20] crazy pills --- netlify.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/netlify.toml b/netlify.toml index 8764ef9a..4fbf0b70 100644 --- a/netlify.toml +++ b/netlify.toml @@ -7,7 +7,7 @@ port = 3000 autoLaunch = false -[[headers]] - for = "/build/*" - [headers.values] - "Cache-Control" = "public, max-age=31536000, s-maxage=31536000" +# [[headers]] +# for = "/build/*" +# [headers.values] +# "Cache-Control" = "public, max-age=31536000, s-maxage=31536000" From 871b905ad981653a0d7f8aeb4c37753334d5dac8 Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Wed, 22 Feb 2023 15:23:48 -0500 Subject: [PATCH 14/20] crazy pills --- server.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/server.js b/server.js index 1b172209..038b861a 100644 --- a/server.js +++ b/server.js @@ -7,8 +7,3 @@ export default createRequestHandler({ // process.env.NODE_ENV is provided by Remix at compile time mode: process.env.NODE_ENV, }); - -export const config = { - cache: "manual", - path: "/*", -}; From 5a75e57a51eed000639677b8c1ca986a5395d44b Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Wed, 22 Feb 2023 15:24:47 -0500 Subject: [PATCH 15/20] crazy pills --- server.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server.js b/server.js index 038b861a..1b172209 100644 --- a/server.js +++ b/server.js @@ -7,3 +7,8 @@ export default createRequestHandler({ // process.env.NODE_ENV is provided by Remix at compile time mode: process.env.NODE_ENV, }); + +export const config = { + cache: "manual", + path: "/*", +}; From fa3a7c6b4791be4910fb90c677ea1fa5c77a0a03 Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Wed, 22 Feb 2023 15:25:48 -0500 Subject: [PATCH 16/20] crazy pills --- server.js => server.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename server.js => server.ts (100%) diff --git a/server.js b/server.ts similarity index 100% rename from server.js rename to server.ts From 53706076ddca47d0acac5bc46af32bdf311df2f0 Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Wed, 22 Feb 2023 15:32:40 -0500 Subject: [PATCH 17/20] hmm --- netlify-server.ts | 62 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + pnpm-lock.yaml | 20 +++++++++++++++ server.ts | 3 ++- 4 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 netlify-server.ts 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, From 151b4342954d17cee02aa21cc6936ac92b27b223 Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Wed, 22 Feb 2023 15:39:54 -0500 Subject: [PATCH 18/20] maybe continue --- netlify-server.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/netlify-server.ts b/netlify-server.ts index 45e7d928..7c8a02d8 100644 --- a/netlify-server.ts +++ b/netlify-server.ts @@ -32,8 +32,8 @@ export function createRequestHandler({ 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 + console.log('Continuing Remix handler for static file', pathname) + // return } try { const loadContext = (await getLoadContext?.(request, context)) || context From 05a2adaac49a9205376186aebcbaecc5f9906fc9 Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Wed, 22 Feb 2023 15:49:44 -0500 Subject: [PATCH 19/20] hmm --- netlify-server.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/netlify-server.ts b/netlify-server.ts index 7c8a02d8..e4cafd19 100644 --- a/netlify-server.ts +++ b/netlify-server.ts @@ -32,8 +32,8 @@ export function createRequestHandler({ const { pathname } = new URL(request.url) // Skip the handler for static files if (pathname.startsWith(`${assetPath}/`)) { - console.log('Continuing Remix handler for static file', pathname) - // return + console.log('Skipping Remix handler for static file', pathname) + return; } try { const loadContext = (await getLoadContext?.(request, context)) || context From 4f4f62ffadee3df780a21fb0ba164e5c4bc2da05 Mon Sep 17 00:00:00 2001 From: Wes Bos Date: Wed, 22 Feb 2023 16:12:17 -0500 Subject: [PATCH 20/20] Temporary workaround --- netlify-server.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/netlify-server.ts b/netlify-server.ts index e4cafd19..d016a1d5 100644 --- a/netlify-server.ts +++ b/netlify-server.ts @@ -32,8 +32,9 @@ export function createRequestHandler({ 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; + // Temporary fix - passing the request to the Netlify static asset handler causes a 203 Not Content error. Passing the through remix works, but I asssume isn't ideal + // console.log('Skipping Remix handler for static file', pathname) + // return; } try { const loadContext = (await getLoadContext?.(request, context)) || context