diff --git a/docs/src/content/docs/guides/frontend/tailwind.mdx b/docs/src/content/docs/guides/frontend/tailwind.mdx index 08ccb75b4..d7b65bf72 100644 --- a/docs/src/content/docs/guides/frontend/tailwind.mdx +++ b/docs/src/content/docs/guides/frontend/tailwind.mdx @@ -25,12 +25,19 @@ Since the RedwoodSDK is based on React and Vite, we can work through the ["Using import { defineConfig } from "vite"; import tailwindcss from "@tailwindcss/vite"; import { redwood } from "rwsdk/vite"; + import { cloudflare } from "@cloudflare/vite-plugin"; export default defineConfig({ environments: { ssr: {}, }, - plugins: [redwood(), tailwindcss()], + plugins: [ + cloudflare({ + viteEnvironment: { name: "worker" }, + }), + redwood(), + tailwindcss() + ], }); ``` diff --git a/docs/src/content/docs/tutorial/full-stack-app/2-create-app.mdx b/docs/src/content/docs/tutorial/full-stack-app/2-create-app.mdx index 0eda74734..61789c300 100644 --- a/docs/src/content/docs/tutorial/full-stack-app/2-create-app.mdx +++ b/docs/src/content/docs/tutorial/full-stack-app/2-create-app.mdx @@ -127,12 +127,16 @@ Since the RedwoodSDK is based on React and Vite, we can work through the ["Using import { defineConfig } from "vite"; import tailwindcss from '@tailwindcss/vite' import { redwood } from "rwsdk/vite"; + import { cloudflare } from "@cloudflare/vite-plugin"; export default defineConfig({ environments: { ssr: {}, }, plugins: [ + cloudflare({ + viteEnvironment: { name: "worker" }, + }), redwood(), tailwindcss(), ], diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3ebbfcda7..1633105a9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -196,9 +196,15 @@ importers: starters/minimal: dependencies: rwsdk: - specifier: 0.1.0-alpha.18-test.20250623021216 - version: 0.1.0-alpha.18-test.20250623021216(typescript@5.8.3)(vite@6.3.3(@types/node@22.14.0)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.4)(yaml@2.7.0))(webpack@5.97.1)(workerd@1.20250617.0) + specifier: 0.1.0-alpha.19-test.20250623033339 + version: 0.1.0-alpha.19-test.20250623033339(rollup@4.40.0)(typescript@5.8.3)(vite@6.3.3(@types/node@22.14.0)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.4)(yaml@2.7.0))(webpack@5.97.1)(workerd@1.20250617.0) devDependencies: + '@cloudflare/vite-plugin': + specifier: 1.7.4 + version: 1.7.4(rollup@4.40.0)(vite@6.3.3(@types/node@22.14.0)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.4)(yaml@2.7.0))(workerd@1.20250617.0)(wrangler@4.20.5(@cloudflare/workers-types@4.20250407.0)) + '@cloudflare/workers-types': + specifier: ^4.20250407.0 + version: 4.20250407.0 '@types/node': specifier: ^22.14.0 version: 22.14.0 @@ -215,8 +221,8 @@ importers: specifier: ^6.2.6 version: 6.3.3(@types/node@22.14.0)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.4)(yaml@2.7.0) wrangler: - specifier: ^4.20.3 - version: 4.20.3(@cloudflare/workers-types@4.20250407.0) + specifier: ^4.20.5 + version: 4.20.5(@cloudflare/workers-types@4.20250407.0) starters/standard: dependencies: @@ -233,9 +239,15 @@ importers: specifier: ^13.1.1 version: 13.1.1 rwsdk: - specifier: 0.1.0-alpha.18-test.20250623021216 - version: 0.1.0-alpha.18-test.20250623021216(typescript@5.8.3)(vite@6.3.3(@types/node@22.14.0)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.4)(yaml@2.7.0))(webpack@5.97.1)(workerd@1.20250617.0) + specifier: 0.1.0-alpha.19-test.20250623033339 + version: 0.1.0-alpha.19-test.20250623033339(rollup@4.40.0)(typescript@5.8.3)(vite@6.3.3(@types/node@22.14.0)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.4)(yaml@2.7.0))(webpack@5.97.1)(workerd@1.20250617.0) devDependencies: + '@cloudflare/vite-plugin': + specifier: 1.7.4 + version: 1.7.4(rollup@4.40.0)(vite@6.3.3(@types/node@22.14.0)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.4)(yaml@2.7.0))(workerd@1.20250617.0)(wrangler@4.20.5(@cloudflare/workers-types@4.20250407.0)) + '@cloudflare/workers-types': + specifier: ^4.20250407.0 + version: 4.20250407.0 '@types/node': specifier: ^22.14.0 version: 22.14.0 @@ -258,8 +270,8 @@ importers: specifier: ^6.2.6 version: 6.3.3(@types/node@22.14.0)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.4)(yaml@2.7.0) wrangler: - specifier: ^4.20.3 - version: 4.20.3(@cloudflare/workers-types@4.20250407.0) + specifier: ^4.20.5 + version: 4.20.5(@cloudflare/workers-types@4.20250407.0) packages: @@ -3100,11 +3112,6 @@ packages: engines: {node: '>=18.0.0'} hasBin: true - miniflare@4.20250617.1: - resolution: {integrity: sha512-NjwKVzPGCAUgkCOJxHBwgV2Obu3g4/wAJE0JaA9whcYip4VAJwQ1fU9TMtoKLY91jD9ANR221+CqLyqxennjqg==} - engines: {node: '>=18.0.0'} - hasBin: true - miniflare@4.20250617.3: resolution: {integrity: sha512-j+LZycT11UdlVeNdaqD0XdNnYnqAL+wXmboz+tNPFgTq6zhD489Ujj3BfSDyEHDCA9UFBLbkc5ByGWBh+pYZ5Q==} engines: {node: '>=18.0.0'} @@ -3573,8 +3580,8 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - rwsdk@0.1.0-alpha.18-test.20250623021216: - resolution: {integrity: sha512-xXA0kqai9uEXHJahB3g29MoFy61RCQGlBV5U4FYb4T5rz31VgseeBoedcOL+kPpWSNGvzj4xGasZGTVUzOsWTA==} + rwsdk@0.1.0-alpha.19-test.20250623033339: + resolution: {integrity: sha512-btCeZDohV1fb7QuYdoIHzKV68lCzfyGiQWc9noInqmGyBurUf6xxicyM4A+IFsfgTwVXL2L4E3padnPacMYmgg==} hasBin: true peerDependencies: vite: ^6.2.6 @@ -4262,16 +4269,6 @@ packages: engines: {node: '>=16'} hasBin: true - wrangler@4.20.3: - resolution: {integrity: sha512-ugvmi43CFPbjeQFfhU7EqE1V0ek6ZFv80jzwHcPk/7jPFmOA4ahT5uUU1ga5ZP6vz6lUuG2bLnyl1T5qJah0cg==} - engines: {node: '>=18.0.0'} - hasBin: true - peerDependencies: - '@cloudflare/workers-types': ^4.20250617.0 - peerDependenciesMeta: - '@cloudflare/workers-types': - optional: true - wrangler@4.20.5: resolution: {integrity: sha512-tmiyt2vBHszhdzJEDbCpFLU2RiV7/QzvGMV07Zaz4ptqiU2h/lTojyNJAugPpSFNiOuY+k0g3ENNTDQqoUkMFA==} engines: {node: '>=18.0.0'} @@ -4783,25 +4780,6 @@ snapshots: - utf-8-validate - workerd - '@cloudflare/vite-plugin@1.7.4(vite@6.3.3(@types/node@22.14.0)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.4)(yaml@2.7.0))(workerd@1.20250617.0)(wrangler@4.20.5(@cloudflare/workers-types@4.20250407.0))': - dependencies: - '@cloudflare/unenv-preset': 2.3.3(unenv@2.0.0-rc.17)(workerd@1.20250617.0) - '@mjackson/node-fetch-server': 0.6.1 - '@rollup/plugin-replace': 6.0.2(rollup@4.40.0) - get-port: 7.1.0 - miniflare: 4.20250617.3 - picocolors: 1.1.1 - tinyglobby: 0.2.13 - unenv: 2.0.0-rc.17 - vite: 6.3.3(@types/node@22.14.0)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.4)(yaml@2.7.0) - wrangler: 4.20.5(@cloudflare/workers-types@4.20250407.0) - ws: 8.18.0 - transitivePeerDependencies: - - bufferutil - - rollup - - utf-8-validate - - workerd - '@cloudflare/workerd-darwin-64@1.20250405.0': optional: true @@ -7715,24 +7693,6 @@ snapshots: - bufferutil - utf-8-validate - miniflare@4.20250617.1: - dependencies: - '@cspotcode/source-map-support': 0.8.1 - acorn: 8.14.0 - acorn-walk: 8.3.2 - exit-hook: 2.2.1 - glob-to-regexp: 0.4.1 - sharp: 0.33.5 - stoppable: 1.1.0 - undici: 5.28.5 - workerd: 1.20250617.0 - ws: 8.18.0 - youch: 3.3.4 - zod: 3.22.3 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - miniflare@4.20250617.3: dependencies: '@cspotcode/source-map-support': 0.8.1 @@ -8352,10 +8312,10 @@ snapshots: dependencies: queue-microtask: 1.2.3 - rwsdk@0.1.0-alpha.18-test.20250623021216(typescript@5.8.3)(vite@6.3.3(@types/node@22.14.0)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.4)(yaml@2.7.0))(webpack@5.97.1)(workerd@1.20250617.0): + rwsdk@0.1.0-alpha.19-test.20250623033339(rollup@4.40.0)(typescript@5.8.3)(vite@6.3.3(@types/node@22.14.0)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.4)(yaml@2.7.0))(webpack@5.97.1)(workerd@1.20250617.0): dependencies: '@ast-grep/napi': 0.38.5 - '@cloudflare/vite-plugin': 1.7.4(vite@6.3.3(@types/node@22.14.0)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.4)(yaml@2.7.0))(workerd@1.20250617.0)(wrangler@4.20.5(@cloudflare/workers-types@4.20250407.0)) + '@cloudflare/vite-plugin': 1.7.4(rollup@4.40.0)(vite@6.3.3(@types/node@22.14.0)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.4)(yaml@2.7.0))(workerd@1.20250617.0)(wrangler@4.20.5(@cloudflare/workers-types@4.20250407.0)) '@cloudflare/workers-types': 4.20250407.0 '@puppeteer/browsers': 2.10.1 '@types/fs-extra': 11.0.4 @@ -9108,23 +9068,6 @@ snapshots: '@cloudflare/workerd-linux-arm64': 1.20250617.0 '@cloudflare/workerd-windows-64': 1.20250617.0 - wrangler@4.20.3(@cloudflare/workers-types@4.20250407.0): - dependencies: - '@cloudflare/kv-asset-handler': 0.4.0 - '@cloudflare/unenv-preset': 2.3.3(unenv@2.0.0-rc.17)(workerd@1.20250617.0) - blake3-wasm: 2.1.5 - esbuild: 0.25.4 - miniflare: 4.20250617.1 - path-to-regexp: 6.3.0 - unenv: 2.0.0-rc.17 - workerd: 1.20250617.0 - optionalDependencies: - '@cloudflare/workers-types': 4.20250407.0 - fsevents: 2.3.3 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - wrangler@4.20.5(@cloudflare/workers-types@4.20250407.0): dependencies: '@cloudflare/kv-asset-handler': 0.4.0 diff --git a/sdk/package.json b/sdk/package.json index dd7c15094..2e62109d7 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -1,6 +1,6 @@ { "name": "rwsdk", - "version": "0.1.0-alpha.19", + "version": "0.1.0-alpha.19-test.20250623033339", "description": "Build fast, server-driven webapps on Cloudflare with SSR, RSC, and realtime", "type": "module", "bin": { diff --git a/sdk/src/scripts/worker-run.mts b/sdk/src/scripts/worker-run.mts index e4f2fbb6b..8ad270e64 100644 --- a/sdk/src/scripts/worker-run.mts +++ b/sdk/src/scripts/worker-run.mts @@ -54,6 +54,7 @@ export const runWorkerScript = async (relativeScriptPath: string) => { plugins: [ redwood({ configPath: tmpWorkerPath.path, + includeCloudflarePlugin: true, entry: { worker: scriptPath, }, diff --git a/sdk/src/vite/hasOwnCloudflareVitePlugin.mts b/sdk/src/vite/hasOwnCloudflareVitePlugin.mts new file mode 100644 index 000000000..106bf0e47 --- /dev/null +++ b/sdk/src/vite/hasOwnCloudflareVitePlugin.mts @@ -0,0 +1,20 @@ +import { readFile } from "fs/promises"; +import path from "path"; + +export async function hasOwnCloudflareVitePlugin({ + rootProjectDir, +}: { + rootProjectDir: string; +}) { + const packageJsonPath = path.join(rootProjectDir, "package.json"); + try { + const packageJson = JSON.parse(await readFile(packageJsonPath, "utf-8")); + return !!( + packageJson.dependencies?.["@cloudflare/vite-plugin"] || + packageJson.devDependencies?.["@cloudflare/vite-plugin"] + ); + } catch (error) { + console.error("Error reading package.json:", error); + return false; + } +} diff --git a/sdk/src/vite/miniflarePlugin.mts b/sdk/src/vite/miniflareHMRPlugin.mts similarity index 92% rename from sdk/src/vite/miniflarePlugin.mts rename to sdk/src/vite/miniflareHMRPlugin.mts index 4c1304c60..50daa6f5d 100644 --- a/sdk/src/vite/miniflarePlugin.mts +++ b/sdk/src/vite/miniflareHMRPlugin.mts @@ -1,5 +1,4 @@ import { HotUpdateOptions, Plugin } from "vite"; -import { cloudflare } from "@cloudflare/vite-plugin"; import { resolve } from "node:path"; import colors from "picocolors"; import { readFile } from "node:fs/promises"; @@ -7,10 +6,6 @@ import { readFile } from "node:fs/promises"; import { getShortName } from "../lib/getShortName.mjs"; import { pathExists } from "fs-extra"; -type BasePluginOptions = Parameters[0]; - -type MiniflarePluginOptions = BasePluginOptions & {}; - const hasEntryAsAncestor = ( module: any, entryFile: string, @@ -89,17 +84,15 @@ const isUseClientModule = async ( } }; -export const miniflarePlugin = ( - givenOptions: MiniflarePluginOptions & { - rootDir: string; - workerEntryPathname: string; - }, -): (Plugin | Plugin[])[] => [ - cloudflare(givenOptions), +export const miniflareHMRPlugin = (givenOptions: { + rootDir: string; + viteEnvironment: { name: string }; + workerEntryPathname: string; +}): (Plugin | Plugin[])[] => [ { name: "rwsdk:miniflare-hmr", async hotUpdate(ctx) { - const environment = givenOptions.viteEnvironment?.name ?? "worker"; + const environment = givenOptions.viteEnvironment.name; const entry = givenOptions.workerEntryPathname; if (!["client", environment].includes(this.environment.name)) { diff --git a/sdk/src/vite/redwoodPlugin.mts b/sdk/src/vite/redwoodPlugin.mts index 2c3c8ebe7..c4a7d803f 100644 --- a/sdk/src/vite/redwoodPlugin.mts +++ b/sdk/src/vite/redwoodPlugin.mts @@ -1,5 +1,7 @@ import { resolve } from "node:path"; import { InlineConfig } from "vite"; +import { cloudflare } from "@cloudflare/vite-plugin"; +import { hasOwnCloudflareVitePlugin } from "./hasOwnCloudflareVitePlugin.mjs"; import reactPlugin from "@vitejs/plugin-react"; import tsconfigPaths from "vite-tsconfig-paths"; @@ -8,7 +10,7 @@ import { transformJsxScriptTagsPlugin } from "./transformJsxScriptTagsPlugin.mjs import { directivesPlugin } from "./directivesPlugin.mjs"; import { useClientLookupPlugin } from "./useClientLookupPlugin.mjs"; import { useServerLookupPlugin } from "./useServerLookupPlugin.mjs"; -import { miniflarePlugin } from "./miniflarePlugin.mjs"; +import { miniflareHMRPlugin } from "./miniflareHMRPlugin.mjs"; import { moveStaticAssetsPlugin } from "./moveStaticAssetsPlugin.mjs"; import { configPlugin } from "./configPlugin.mjs"; import { $ } from "../lib/$.mjs"; @@ -26,6 +28,7 @@ export type RedwoodPluginOptions = { silent?: boolean; rootDir?: string; mode?: "development" | "production"; + includeCloudflarePlugin?: boolean; configPath?: string; entry?: { client?: string; @@ -37,6 +40,7 @@ export const redwoodPlugin = async ( options: RedwoodPluginOptions = {}, ): Promise => { const projectRootDir = process.cwd(); + const mode = options.mode ?? (process.env.NODE_ENV === "development" ? "development" : "production"); @@ -52,6 +56,10 @@ export const redwoodPlugin = async ( const clientFiles = new Set(); const serverFiles = new Set(); + const shouldIncludeCloudflarePlugin = + options.includeCloudflarePlugin ?? + !(await hasOwnCloudflareVitePlugin({ rootProjectDir: projectRootDir })); + // context(justinvdm, 31 Mar 2025): We assume that if there is no .wrangler directory, // then this is fresh install, and we run `npm run dev:init` here. if ( @@ -69,6 +77,7 @@ export const redwoodPlugin = async ( stdio: ["ignore", "inherit", "inherit"], })`npm run dev:init`; } + return [ devServerTimingPlugin(), configPlugin({ @@ -85,12 +94,17 @@ export const redwoodPlugin = async ( }), reactConditionsResolverPlugin(), tsconfigPaths({ root: projectRootDir }), - miniflarePlugin({ + shouldIncludeCloudflarePlugin + ? cloudflare({ + viteEnvironment: { name: "worker" }, + configPath: + options.configPath ?? (await findWranglerConfig(projectRootDir)), + }) + : [], + miniflareHMRPlugin({ rootDir: projectRootDir, viteEnvironment: { name: "worker" }, workerEntryPathname, - configPath: - options.configPath ?? (await findWranglerConfig(projectRootDir)), }), reactPlugin(), directivesPlugin({ diff --git a/starters/minimal/package.json b/starters/minimal/package.json index bebe9c84d..cc025b78b 100644 --- a/starters/minimal/package.json +++ b/starters/minimal/package.json @@ -22,15 +22,17 @@ "types": "tsc" }, "dependencies": { - "rwsdk": "0.1.0-alpha.18-test.20250623021216" + "rwsdk": "0.1.0-alpha.19-test.20250623033339" }, "devDependencies": { + "@cloudflare/vite-plugin": "1.7.4", + "@cloudflare/workers-types": "^4.20250407.0", "@types/node": "^22.14.0", "@types/react": "^19.1.2", "@types/react-dom": "^19.1.2", "typescript": "^5.8.3", "vite": "^6.2.6", - "wrangler": "^4.20.3" + "wrangler": "^4.20.5" }, "pnpm": { "onlyBuiltDependencies": [ diff --git a/starters/minimal/vite.config.mts b/starters/minimal/vite.config.mts index c1ad0bbcd..89b7258b9 100644 --- a/starters/minimal/vite.config.mts +++ b/starters/minimal/vite.config.mts @@ -1,6 +1,12 @@ import { defineConfig } from "vite"; import { redwood } from "rwsdk/vite"; +import { cloudflare } from "@cloudflare/vite-plugin"; export default defineConfig({ - plugins: [redwood()], + plugins: [ + cloudflare({ + viteEnvironment: { name: "worker" }, + }), + redwood(), + ], }); diff --git a/starters/standard/package.json b/starters/standard/package.json index 4169473e5..00e5ed81a 100644 --- a/starters/standard/package.json +++ b/starters/standard/package.json @@ -31,9 +31,11 @@ "@prisma/client": "~6.8.2", "@simplewebauthn/browser": "^13.1.0", "@simplewebauthn/server": "^13.1.1", - "rwsdk": "0.1.0-alpha.18-test.20250623021216" + "rwsdk": "0.1.0-alpha.19-test.20250623033339" }, "devDependencies": { + "@cloudflare/vite-plugin": "1.7.4", + "@cloudflare/workers-types": "^4.20250407.0", "@types/node": "^22.14.0", "@types/react": "^19.1.2", "@types/react-dom": "^19.1.2", @@ -41,7 +43,7 @@ "typescript": "^5.8.3", "vibe-rules": "^0.2.31", "vite": "^6.2.6", - "wrangler": "^4.20.3" + "wrangler": "^4.20.5" }, "pnpm": { "onlyBuiltDependencies": [ diff --git a/starters/standard/vite.config.mts b/starters/standard/vite.config.mts index c1ad0bbcd..89b7258b9 100644 --- a/starters/standard/vite.config.mts +++ b/starters/standard/vite.config.mts @@ -1,6 +1,12 @@ import { defineConfig } from "vite"; import { redwood } from "rwsdk/vite"; +import { cloudflare } from "@cloudflare/vite-plugin"; export default defineConfig({ - plugins: [redwood()], + plugins: [ + cloudflare({ + viteEnvironment: { name: "worker" }, + }), + redwood(), + ], });