diff --git a/netlify/dev-server.js b/netlify/dev-server.js deleted file mode 100644 index 717f7ec..0000000 --- a/netlify/dev-server.js +++ /dev/null @@ -1,34 +0,0 @@ -import { createRequestListener } from "@mjackson/node-fetch-server"; -import express from "express"; - -const PORT = Number.parseInt(process.env.PORT || "3000"); - -const app = express(); -app.disable("x-powered-by"); - -console.log("Starting development server"); -const viteDevServer = await import("vite").then((vite) => - vite.createServer({ - server: { middlewareMode: true }, - }) -); -app.use(viteDevServer.middlewares); -app.use(async (req, res, next) => { - try { - return await createRequestListener(async (request) => { - const source = await viteDevServer.ssrLoadModule("./server/app.ts"); - return await source.default(request, { - // TODO: Mock any required netlify functions context - }); - })(req, res); - } catch (error) { - if (typeof error === "object" && error instanceof Error) { - viteDevServer.ssrFixStacktrace(error); - } - next(error); - } -}); - -app.listen(PORT, () => { - console.log(`Server is running on http://localhost:${PORT}`); -}); diff --git a/netlify/netlify.toml b/netlify/netlify.toml index 2088101..517798d 100644 --- a/netlify/netlify.toml +++ b/netlify/netlify.toml @@ -1,10 +1,9 @@ [build] -command = "npm run build" +command = "react-router build" publish = "build/client" [dev] -command = "npm run dev" -framework = "vite" +command = "react-router dev" # Set immutable caching for static files, because they have fingerprinted filenames diff --git a/netlify/netlify/prepare.js b/netlify/netlify/prepare.js deleted file mode 100644 index b4a47a3..0000000 --- a/netlify/netlify/prepare.js +++ /dev/null @@ -1,11 +0,0 @@ -import * as fsp from "node:fs/promises"; - -await fsp - .rm(".netlify/functions-internal", { recursive: true }) - .catch(() => {}); -await fsp.mkdir(".netlify/functions-internal", { recursive: true }); -await fsp.cp("build/server/", ".netlify/functions-internal/handler", { - recursive: true, -}); - -// .netlify/functions-internal diff --git a/netlify/package.json b/netlify/package.json index 6f75212..49cfc2d 100644 --- a/netlify/package.json +++ b/netlify/package.json @@ -2,29 +2,24 @@ "private": true, "type": "module", "scripts": { - "build": "react-router build && node netlify/prepare.js", - "dev": "cross-env NODE_ENV=development node ./dev-server.js", + "build": "react-router build", + "dev": "react-router dev", "start": "netlify serve", "typecheck": "react-router typegen && tsc" }, "dependencies": { - "@netlify/functions": "2.8.2", "@react-router/node": "*", - "isbot": "^5.1.17", "react": "^19.0.0", "react-dom": "^19.0.0", "react-router": "*" }, "devDependencies": { - "@mjackson/node-fetch-server": "0.3.0", + "@netlify/vite-plugin-react-router": "^1.0.0", "@react-router/dev": "*", "@tailwindcss/vite": "^4.0.0", - "@types/express": "^5.0.0", "@types/react": "^19.0.1", "@types/react-dom": "^19.0.1", "autoprefixer": "^10.4.20", - "cross-env": "^7.0.3", - "express": "^4.21.1", "netlify-cli": "^17.38.0", "postcss": "^8.4.49", "tailwindcss": "^4.0.0", diff --git a/netlify/server/app.ts b/netlify/server/app.ts deleted file mode 100644 index a77f4c2..0000000 --- a/netlify/server/app.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { Config, Context } from "@netlify/functions"; -import { createRequestHandler } from "react-router"; - -declare module "react-router" { - interface AppLoadContext { - VALUE_FROM_NETLIFY: string; - } -} - -const requestHandler = createRequestHandler( - // @ts-expect-error - virtual module provided by React Router at build time - () => import("virtual:react-router/server-build"), - import.meta.env.MODE -); - -export default async (request: Request, context: Context) => { - return requestHandler(request, { - VALUE_FROM_NETLIFY: "Hello from Netlify", - }); -}; - -export const config: Config = { - path: "/*", - preferStatic: true, -}; diff --git a/netlify/vite.config.ts b/netlify/vite.config.ts index 4fee863..5d767d2 100644 --- a/netlify/vite.config.ts +++ b/netlify/vite.config.ts @@ -2,6 +2,7 @@ import { reactRouter } from "@react-router/dev/vite"; import tailwindcss from "@tailwindcss/vite"; import { defineConfig } from "vite"; import tsconfigPaths from "vite-tsconfig-paths"; +import netlifyPlugin from "@netlify/vite-plugin-react-router"; export default defineConfig(({ isSsrBuild }) => ({ build: { @@ -11,5 +12,5 @@ export default defineConfig(({ isSsrBuild }) => ({ } : undefined, }, - plugins: [tailwindcss(), reactRouter(), tsconfigPaths()], + plugins: [tailwindcss(), reactRouter(), tsconfigPaths(), netlifyPlugin()], })); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 63063b9..6cf3f73 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -280,15 +280,9 @@ importers: netlify: dependencies: - '@netlify/functions': - specifier: 2.8.2 - version: 2.8.2 '@react-router/node': specifier: '*' version: 7.1.1(react-router@7.1.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(typescript@5.7.2) - isbot: - specifier: ^5.1.17 - version: 5.1.17 react: specifier: ^19.0.0 version: 19.0.0 @@ -299,18 +293,15 @@ importers: specifier: '*' version: 7.1.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) devDependencies: - '@mjackson/node-fetch-server': - specifier: 0.3.0 - version: 0.3.0 + '@netlify/vite-plugin-react-router': + specifier: ^1.0.0 + version: 1.0.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.2)(vite@5.4.11(@types/node@22.9.1)(lightningcss@1.29.1)) '@react-router/dev': specifier: '*' version: 7.1.1(@react-router/serve@7.3.0(react-router@7.1.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(typescript@5.7.2))(@types/node@22.9.1)(babel-plugin-macros@3.1.0)(jiti@2.4.2)(lightningcss@1.29.1)(react-router@7.1.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(tsx@4.19.2)(typescript@5.7.2)(vite@5.4.11(@types/node@22.9.1)(lightningcss@1.29.1))(wrangler@3.114.2(@cloudflare/workers-types@4.20250317.0))(yaml@2.6.1) '@tailwindcss/vite': specifier: ^4.0.0 version: 4.0.0(vite@5.4.11(@types/node@22.9.1)(lightningcss@1.29.1)) - '@types/express': - specifier: ^5.0.0 - version: 5.0.0 '@types/react': specifier: ^19.0.1 version: 19.0.1 @@ -320,15 +311,9 @@ importers: autoprefixer: specifier: ^10.4.20 version: 10.4.20(postcss@8.4.49) - cross-env: - specifier: ^7.0.3 - version: 7.0.3 - express: - specifier: ^4.21.1 - version: 4.21.1 netlify-cli: specifier: ^17.38.0 - version: 17.38.0(@types/express@5.0.0)(@types/node@22.9.1)(picomatch@4.0.2) + version: 17.38.0(@types/node@22.9.1)(picomatch@4.0.2) postcss: specifier: ^8.4.49 version: 8.4.49 @@ -2369,9 +2354,6 @@ packages: '@mjackson/node-fetch-server@0.2.0': resolution: {integrity: sha512-EMlH1e30yzmTpGLQjlFmaDAjyOeZhng1/XCd7DExR8PNAnG/G1tyruZxEoUe11ClnwGhGrtsdnyyUx1frSzjng==} - '@mjackson/node-fetch-server@0.3.0': - resolution: {integrity: sha512-p+wzVVjYI6pi+t9hRMZngfwywE4CaPu3ZuYkB3+fkS1bSPAxZikXeIdeuOTiy5oqltOOODG0hoe55FR2PRmF/A==} - '@netlify/binary-info@1.0.0': resolution: {integrity: sha512-4wMPu9iN3/HL97QblBsBay3E1etIciR84izI3U+4iALY+JHCrI+a2jO0qbAZ/nxKoegypYEaiiqWXylm+/zfrw==} @@ -2423,10 +2405,6 @@ packages: resolution: {integrity: sha512-/b2JtJuB3KNN5AIfiH/tan/uM4i6nLj2QFGUL9oID58cMsd73iouRacKu4ct+gxUU78y+/6fiOeYRXbcthdltA==} engines: {node: ^14.16.0 || >=16.0.0} - '@netlify/functions@2.8.2': - resolution: {integrity: sha512-DeoAQh8LuNPvBE4qsKlezjKj0PyXDryOFJfJKo3Z1qZLKzQ21sT314KQKPVjfvw6knqijj+IO+0kHXy/TJiqNA==} - engines: {node: '>=14.0.0'} - '@netlify/git-utils@5.1.1': resolution: {integrity: sha512-oyHieuTZH3rKTmg7EKpGEGa28IFxta2oXuVwpPJI/FJAtBje3UE+yko0eDjNufgm3AyGa8G77trUxgBhInAYuw==} engines: {node: ^14.16.0 || >=16.0.0} @@ -2528,14 +2506,16 @@ packages: resolution: {integrity: sha512-V2B8ZB19heVKa715uOeDkztxLH7uaqZ+9U5fV7BRzbQ2514DO5Vxj9hG0irzuRLfZXZZjp/chPUesv4VVsce/A==} engines: {node: ^14.16.0 || >=16.0.0} - '@netlify/serverless-functions-api@1.26.1': - resolution: {integrity: sha512-q3L9i3HoNfz0SGpTIS4zTcKBbRkxzCRpd169eyiTuk3IwcPC3/85mzLHranlKo2b+HYT0gu37YxGB45aD8A3Tw==} - engines: {node: '>=18.0.0'} - '@netlify/serverless-functions-api@1.31.0': resolution: {integrity: sha512-/ux3fefmw0yGmzRMOqhGrzbAuALtW8HY08bjE4yCk+y8CzB9r9mPd1ApSJe3KlYD+sqDvbQGrEXdifQ/LzUIDQ==} engines: {node: '>=18.0.0'} + '@netlify/vite-plugin-react-router@1.0.0': + resolution: {integrity: sha512-J9xzn2Gdehg3LSEXFrpXLjQm2T2HQEnnlbTH7Ic9mjaz9rwkRmgwbYBn9h5SexQ0mV82jZjhvneblL8VPKiUtQ==} + engines: {node: '>=18'} + peerDependencies: + vite: '>=5.0.0' + '@netlify/zip-it-and-ship-it@9.41.1': resolution: {integrity: sha512-EzXw1+4OJ4mCZUOqVPDQZNM8jf/563utFo1Ph6dYtSR21E1oYlgt6Oib1pyG/bFGufvdtrxw845/1MTCPvXzJA==} engines: {node: ^14.18.0 || >=16.0.0} @@ -3192,6 +3172,16 @@ packages: typescript: optional: true + '@react-router/node@7.0.2': + resolution: {integrity: sha512-6Of5M2wP9QgYlR+boR0ptPjh3UyfaNvPMKQihowTGjAjUZIoNqz4iBn8ClNsLFbT3KQewcnNTHi2p+Ou7S4ZyQ==} + engines: {node: '>=20.0.0'} + peerDependencies: + react-router: 7.0.2 + typescript: ^5.1.0 + peerDependenciesMeta: + typescript: + optional: true + '@react-router/node@7.1.1': resolution: {integrity: sha512-5X79SfJ1IEEsttt0oo9rhO9kgxXyBTKdVBsz3h0WHTkRzbRk0VEpVpBW3PQ1RpkgEaAHwJ8obVl4k4brdDSExA==} engines: {node: '>=20.0.0'} @@ -7350,6 +7340,16 @@ packages: react-router: '>=7.0.0' vite: '>=5.0.0' + react-router@7.0.2: + resolution: {integrity: sha512-m5AcPfTRUcjwmhBzOJGEl6Y7+Crqyju0+TgTQxoS4SO+BkWbhOrcfZNq6wSWdl2BBbJbsAoBUb8ZacOFT+/JlA==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + peerDependenciesMeta: + react-dom: + optional: true + react-router@7.1.1: resolution: {integrity: sha512-39sXJkftkKWRZ2oJtHhCxmoCrBCULr/HAH4IT5DHlgu/Q0FCPV0S4Lx+abjDTx/74xoZzNYDYbOZWlJjruyuDQ==} engines: {node: '>=20.0.0'} @@ -9922,8 +9922,6 @@ snapshots: '@mjackson/node-fetch-server@0.2.0': {} - '@mjackson/node-fetch-server@0.3.0': {} - '@netlify/binary-info@1.0.0': {} '@netlify/blobs@7.4.0': {} @@ -10101,10 +10099,6 @@ snapshots: - encoding - supports-color - '@netlify/functions@2.8.2': - dependencies: - '@netlify/serverless-functions-api': 1.26.1 - '@netlify/git-utils@5.1.1': dependencies: execa: 6.1.0 @@ -10178,15 +10172,21 @@ snapshots: dependencies: execa: 6.1.0 - '@netlify/serverless-functions-api@1.26.1': + '@netlify/serverless-functions-api@1.31.0': dependencies: '@netlify/node-cookies': 0.1.0 urlpattern-polyfill: 8.0.2 - '@netlify/serverless-functions-api@1.31.0': + '@netlify/vite-plugin-react-router@1.0.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.2)(vite@5.4.11(@types/node@22.9.1)(lightningcss@1.29.1))': dependencies: - '@netlify/node-cookies': 0.1.0 - urlpattern-polyfill: 8.0.2 + '@react-router/node': 7.0.2(react-router@7.0.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(typescript@5.7.2) + isbot: 5.1.17 + react-router: 7.0.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + vite: 5.4.11(@types/node@22.9.1)(lightningcss@1.29.1) + transitivePeerDependencies: + - react + - react-dom + - typescript '@netlify/zip-it-and-ship-it@9.41.1(supports-color@9.4.0)': dependencies: @@ -11228,6 +11228,16 @@ snapshots: optionalDependencies: typescript: 5.7.2 + '@react-router/node@7.0.2(react-router@7.0.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(typescript@5.7.2)': + dependencies: + '@mjackson/node-fetch-server': 0.2.0 + react-router: 7.0.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + source-map-support: 0.5.21 + stream-slice: 0.1.2 + undici: 6.21.0 + optionalDependencies: + typescript: 5.7.2 + '@react-router/node@7.1.1(react-router@7.1.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(typescript@5.7.2)': dependencies: '@mjackson/node-fetch-server': 0.2.0 @@ -14009,15 +14019,13 @@ snapshots: statuses: 2.0.1 toidentifier: 1.0.1 - http-proxy-middleware@2.0.7(@types/express@5.0.0)(debug@4.3.7): + http-proxy-middleware@2.0.7(debug@4.3.7): dependencies: '@types/http-proxy': 1.17.15 http-proxy: 1.18.1(debug@4.3.7) is-glob: 4.0.3 is-plain-obj: 3.0.0 micromatch: 4.0.8 - optionalDependencies: - '@types/express': 5.0.0 transitivePeerDependencies: - debug @@ -14799,7 +14807,7 @@ snapshots: nested-error-stacks@2.1.1: {} - netlify-cli@17.38.0(@types/express@5.0.0)(@types/node@22.9.1)(picomatch@4.0.2): + netlify-cli@17.38.0(@types/node@22.9.1)(picomatch@4.0.2): dependencies: '@bugsnag/js': 7.25.0 '@fastify/static': 7.0.4 @@ -14856,7 +14864,7 @@ snapshots: hasbin: 1.2.3 hasha: 5.2.2 http-proxy: 1.18.1(debug@4.3.7) - http-proxy-middleware: 2.0.7(@types/express@5.0.0)(debug@4.3.7) + http-proxy-middleware: 2.0.7(debug@4.3.7) https-proxy-agent: 7.0.5 inquirer: 6.5.2 inquirer-autocomplete-prompt: 1.4.0(inquirer@6.5.2) @@ -15717,6 +15725,16 @@ snapshots: - '@types/react-dom' - supports-color + react-router@7.0.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + dependencies: + '@types/cookie': 0.6.0 + cookie: 1.0.1 + react: 19.0.0 + set-cookie-parser: 2.7.1 + turbo-stream: 2.4.0 + optionalDependencies: + react-dom: 19.0.0(react@19.0.0) + react-router@7.1.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0): dependencies: '@types/cookie': 0.6.0