From f3f42f272351a3a65ce25d2ace07f6f7a5ae868a Mon Sep 17 00:00:00 2001 From: cod1k Date: Thu, 24 Apr 2025 14:19:46 +0300 Subject: [PATCH 1/8] Add support for `run_worker_first` flag in Miniflare options This update introduces support for the `run_worker_first` flag when configuring Miniflare options. A new test suite ensures proper handling of this flag, including scenarios where it is undefined. Additionally, the `miniflare-options` logic was updated to pass the flag to the worker configuration when specified. --- .../__tests__/get-miniflare-options.spec.ts | 79 +++++++++++++++++++ .../src/miniflare-options.ts | 3 + 2 files changed, 82 insertions(+) create mode 100644 packages/vite-plugin-cloudflare/src/__tests__/get-miniflare-options.spec.ts diff --git a/packages/vite-plugin-cloudflare/src/__tests__/get-miniflare-options.spec.ts b/packages/vite-plugin-cloudflare/src/__tests__/get-miniflare-options.spec.ts new file mode 100644 index 000000000000..ef22a428aff1 --- /dev/null +++ b/packages/vite-plugin-cloudflare/src/__tests__/get-miniflare-options.spec.ts @@ -0,0 +1,79 @@ +import { + afterAll, + afterEach, + beforeAll, + describe, + expect, + test, + vi, +} from "vitest"; +import { ROUTER_WORKER_NAME } from "../constants"; +import { getDevMiniflareOptions } from "../miniflare-options"; +import type { WorkerOptions } from "miniflare"; + +describe("getDevMiniflareOptions", () => { + beforeAll(() => { + vi.mock("fs"); + vi.mock("path"); + vi.mock("wrangler", () => ({ + unstable_getMiniflareWorkerOptions: vi.fn(() => ({ + externalWorkers: {}, + workerOptions: {}, + })), + })); + }); + afterEach(() => { + vi.resetAllMocks(); + }); + afterAll(() => { + vi.restoreAllMocks(); + }); + test.each([ + { run_worker_first: true }, + { run_worker_first: false }, + { run_worker_first: undefined }, + ])( + "Should consider run_worker_first=$run_worker_first flag", + ({ run_worker_first }) => { + // @ts-expect-error + const mf_options: { workers: WorkerOptions[] } = getDevMiniflareOptions( + { + type: "workers", + entryWorkerEnvironmentName: "test", + workers: { + // @ts-expect-error + test: { + assets: { + run_worker_first, + }, + }, + }, + }, + { config: { logLevel: "info" } }, + false + ); + expect(mf_options).toMatchObject({ workers: expect.any(Array) }); + const worker = mf_options.workers.find( + (worker) => worker.name === ROUTER_WORKER_NAME + ); + expect(worker).toBeDefined(); + if (run_worker_first === undefined) { + expect(worker).toMatchObject({ + bindings: { + CONFIG: expect.not.objectContaining({ + invoke_user_worker_ahead_of_assets: expect.anything(), + }), + }, + }); + } else { + expect(worker).toMatchObject({ + bindings: { + CONFIG: { + invoke_user_worker_ahead_of_assets: run_worker_first, + }, + }, + }); + } + } + ); +}); diff --git a/packages/vite-plugin-cloudflare/src/miniflare-options.ts b/packages/vite-plugin-cloudflare/src/miniflare-options.ts index bb7a745b1aa8..4421c9813dc1 100644 --- a/packages/vite-plugin-cloudflare/src/miniflare-options.ts +++ b/packages/vite-plugin-cloudflare/src/miniflare-options.ts @@ -219,6 +219,9 @@ export function getDevMiniflareOptions( bindings: { CONFIG: { has_user_worker: resolvedPluginConfig.type === "workers", + ...(typeof assetsConfig.run_worker_first === "boolean" && { + invoke_user_worker_ahead_of_assets: assetsConfig.run_worker_first, + }), }, }, serviceBindings: { From 9ba627e26e0e07430d8286f9785754802ecb1b27 Mon Sep 17 00:00:00 2001 From: cod1k Date: Thu, 24 Apr 2025 14:35:02 +0300 Subject: [PATCH 2/8] changeset file included --- .changeset/all-doors-pick.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/all-doors-pick.md diff --git a/.changeset/all-doors-pick.md b/.changeset/all-doors-pick.md new file mode 100644 index 000000000000..378dc9cd285e --- /dev/null +++ b/.changeset/all-doors-pick.md @@ -0,0 +1,5 @@ +--- +"@cloudflare/vite-plugin": patch +--- + +Add support for run_worker_first flag in Miniflare options From 2fcd8872535ec608aeaa9bda69170429de8422d5 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Fri, 14 Mar 2025 14:45:06 +0000 Subject: [PATCH 3/8] add support for `run_worker_first` --- .changeset/all-doors-pick.md | 2 +- .../__tests__/run-worker-first.spec.ts | 42 ++++++++++++ .../playground/run-worker-first/index.html | 13 ++++ .../run-worker-first/middleware/index.ts | 25 +++++++ .../playground/run-worker-first/package.json | 26 +++++++ .../run-worker-first/public/admin/secret.svg | 26 +++++++ .../run-worker-first/public/vite.svg | 1 + .../playground/run-worker-first/src/App.css | 42 ++++++++++++ .../playground/run-worker-first/src/App.tsx | 54 +++++++++++++++ .../run-worker-first/src/assets/react.svg | 1 + .../playground/run-worker-first/src/index.css | 68 +++++++++++++++++++ .../playground/run-worker-first/src/main.tsx | 10 +++ .../run-worker-first/src/vite-env.d.ts | 1 + .../run-worker-first/tsconfig.client.json | 4 ++ .../playground/run-worker-first/tsconfig.json | 8 +++ .../run-worker-first/tsconfig.node.json | 4 ++ .../run-worker-first/tsconfig.worker.json | 4 ++ .../playground/run-worker-first/turbo.json | 9 +++ .../run-worker-first/vite.config.ts | 7 ++ .../playground/run-worker-first/wrangler.toml | 4 ++ .../src/miniflare-options.ts | 5 +- pnpm-lock.yaml | 37 ++++++++++ 22 files changed, 389 insertions(+), 4 deletions(-) create mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/__tests__/run-worker-first.spec.ts create mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/index.html create mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/middleware/index.ts create mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/package.json create mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/public/admin/secret.svg create mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/public/vite.svg create mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/src/App.css create mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/src/App.tsx create mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/src/assets/react.svg create mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/src/index.css create mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/src/main.tsx create mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/src/vite-env.d.ts create mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/tsconfig.client.json create mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/tsconfig.json create mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/tsconfig.node.json create mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/tsconfig.worker.json create mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/turbo.json create mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/vite.config.ts create mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/wrangler.toml diff --git a/.changeset/all-doors-pick.md b/.changeset/all-doors-pick.md index 378dc9cd285e..89301fbd2970 100644 --- a/.changeset/all-doors-pick.md +++ b/.changeset/all-doors-pick.md @@ -2,4 +2,4 @@ "@cloudflare/vite-plugin": patch --- -Add support for run_worker_first flag in Miniflare options +Do not ignore `run_worker_first` in `vite preview` mode. diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/__tests__/run-worker-first.spec.ts b/packages/vite-plugin-cloudflare/playground/run-worker-first/__tests__/run-worker-first.spec.ts new file mode 100644 index 000000000000..122b138a0807 --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/__tests__/run-worker-first.spec.ts @@ -0,0 +1,42 @@ +import { describe, expect, test } from "vitest"; +import { isBuild, page, viteTestUrl } from "../../__test-utils__"; + +describe.skipIf(!isBuild)("run_worker_first support", () => { + test("returns the correct home page", async () => { + const content = await page.textContent("h1"); + expect(content).toBe("Vite + React"); + }); + + test("returns the response from the API", async () => { + const button = page.getByRole("button", { name: "get-name" }); + const contentBefore = await button.innerText(); + expect(contentBefore).toBe("Name from API is: unknown"); + const responsePromise = page.waitForResponse((response) => + response.url().endsWith("/api/") + ); + await button.click(); + await responsePromise; + const contentAfter = await button.innerText(); + expect(contentAfter).toBe("Name from API is: Cloudflare"); + }); + + test("returns UNAUTH for the admin page", async () => { + const response = await fetch(viteTestUrl + "/admin"); + expect(response.status).toBe(401); + }); + + test("returns UNAUTH for an admin image", async () => { + const response = await fetch(viteTestUrl + "/admin/secret.svg"); + expect(response.status).toBe(401); + }); + + test("returns response for authorized admin page", async () => { + const response = await fetch(viteTestUrl + "/admin?auth=xxx"); + expect(response.status).toBe(200); + }); + + test("returns response for authorized admin image", async () => { + const response = await fetch(viteTestUrl + "/admin/secret.svg?auth=xxx"); + expect(response.status).toBe(200); + }); +}); diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/index.html b/packages/vite-plugin-cloudflare/playground/run-worker-first/index.html new file mode 100644 index 000000000000..ef80c79b33a5 --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + React + TS + + +
+ + + diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/middleware/index.ts b/packages/vite-plugin-cloudflare/playground/run-worker-first/middleware/index.ts new file mode 100644 index 000000000000..f5b941a6a8a1 --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/middleware/index.ts @@ -0,0 +1,25 @@ +interface Env { + ASSETS: Fetcher; +} + +export default { + async fetch(request, env) { + const url = new URL(request.url); + + // Protect assets in the `/admin` directory from "unauthorized" access! + if (url.pathname.startsWith("/admin")) { + const auth = url.searchParams.get("auth"); + if (!auth) { + return new Response("Unauthorized access", { status: 401 }); + } + } + + if (url.pathname.startsWith("/api/")) { + return Response.json({ + name: "Cloudflare", + }); + } + + return env.ASSETS.fetch(request); + }, +} satisfies ExportedHandler; diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/package.json b/packages/vite-plugin-cloudflare/playground/run-worker-first/package.json new file mode 100644 index 000000000000..636a0336cc69 --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/package.json @@ -0,0 +1,26 @@ +{ + "name": "@playground/run-worker-first", + "private": true, + "type": "module", + "scripts": { + "build": "vite build --app", + "check:types": "tsc --build", + "dev": "vite dev", + "preview": "vite preview" + }, + "dependencies": { + "react": "^19.0.0", + "react-dom": "^19.0.0" + }, + "devDependencies": { + "@cloudflare/vite-plugin": "workspace:*", + "@cloudflare/workers-tsconfig": "workspace:*", + "@cloudflare/workers-types": "^4.20250310.0", + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", + "@vitejs/plugin-react": "^4.3.4", + "typescript": "catalog:default", + "vite": "catalog:vite-plugin", + "wrangler": "workspace:*" + } +} diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/public/admin/secret.svg b/packages/vite-plugin-cloudflare/playground/run-worker-first/public/admin/secret.svg new file mode 100644 index 000000000000..09787d20ebe7 --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/public/admin/secret.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/public/vite.svg b/packages/vite-plugin-cloudflare/playground/run-worker-first/public/vite.svg new file mode 100644 index 000000000000..e7b8dfb1b2a6 --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/src/App.css b/packages/vite-plugin-cloudflare/playground/run-worker-first/src/App.css new file mode 100644 index 000000000000..df674c0d8958 --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/src/App.css @@ -0,0 +1,42 @@ +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: filter 300ms; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/src/App.tsx b/packages/vite-plugin-cloudflare/playground/run-worker-first/src/App.tsx new file mode 100644 index 000000000000..1fa5abd00015 --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/src/App.tsx @@ -0,0 +1,54 @@ +import viteLogo from "/vite.svg"; +import { useState } from "react"; +import reactLogo from "./assets/react.svg"; +import "./App.css"; + +function App() { + const [count, setCount] = useState(0); + const [name, setName] = useState("unknown"); + + return ( + <> +
+ + Vite logo + + + React logo + +
+

Vite + React

+
+ +

+ Edit src/App.tsx and save to test HMR +

+
+
+ +

+ Edit api/index.ts to change the name +

+
+

+ Click on the Vite and React logos to learn more +

+ + ); +} + +export default App; diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/src/assets/react.svg b/packages/vite-plugin-cloudflare/playground/run-worker-first/src/assets/react.svg new file mode 100644 index 000000000000..6c87de9bb335 --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/src/index.css b/packages/vite-plugin-cloudflare/playground/run-worker-first/src/index.css new file mode 100644 index 000000000000..9cfcb00f249a --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/src/index.css @@ -0,0 +1,68 @@ +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/src/main.tsx b/packages/vite-plugin-cloudflare/playground/run-worker-first/src/main.tsx new file mode 100644 index 000000000000..b310b355463c --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/src/main.tsx @@ -0,0 +1,10 @@ +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import "./index.css"; +import App from "./App.tsx"; + +createRoot(document.getElementById("root")!).render( + + + +); diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/src/vite-env.d.ts b/packages/vite-plugin-cloudflare/playground/run-worker-first/src/vite-env.d.ts new file mode 100644 index 000000000000..11f02fe2a006 --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/tsconfig.client.json b/packages/vite-plugin-cloudflare/playground/run-worker-first/tsconfig.client.json new file mode 100644 index 000000000000..719bc3b2504b --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/tsconfig.client.json @@ -0,0 +1,4 @@ +{ + "extends": ["@cloudflare/workers-tsconfig/react.json"], + "include": ["src"] +} diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/tsconfig.json b/packages/vite-plugin-cloudflare/playground/run-worker-first/tsconfig.json new file mode 100644 index 000000000000..f4ac20b7cbcf --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/tsconfig.json @@ -0,0 +1,8 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.node.json" }, + { "path": "./tsconfig.client.json" }, + { "path": "./tsconfig.worker.json" } + ] +} diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/tsconfig.node.json b/packages/vite-plugin-cloudflare/playground/run-worker-first/tsconfig.node.json new file mode 100644 index 000000000000..773be9834af5 --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/tsconfig.node.json @@ -0,0 +1,4 @@ +{ + "extends": ["@cloudflare/workers-tsconfig/base.json"], + "include": ["vite.config.ts", "__tests__"] +} diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/tsconfig.worker.json b/packages/vite-plugin-cloudflare/playground/run-worker-first/tsconfig.worker.json new file mode 100644 index 000000000000..92609dff01c5 --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/tsconfig.worker.json @@ -0,0 +1,4 @@ +{ + "extends": ["@cloudflare/workers-tsconfig/worker.json"], + "include": ["middleware"] +} diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/turbo.json b/packages/vite-plugin-cloudflare/playground/run-worker-first/turbo.json new file mode 100644 index 000000000000..6556dcf3e5e5 --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/turbo.json @@ -0,0 +1,9 @@ +{ + "$schema": "http://turbo.build/schema.json", + "extends": ["//"], + "tasks": { + "build": { + "outputs": ["dist/**"] + } + } +} diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/vite.config.ts b/packages/vite-plugin-cloudflare/playground/run-worker-first/vite.config.ts new file mode 100644 index 000000000000..ecbdd51b7f51 --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/vite.config.ts @@ -0,0 +1,7 @@ +import { cloudflare } from "@cloudflare/vite-plugin"; +import react from "@vitejs/plugin-react"; +import { defineConfig } from "vite"; + +export default defineConfig({ + plugins: [react(), cloudflare({ inspectorPort: false, persistState: false })], +}); diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/wrangler.toml b/packages/vite-plugin-cloudflare/playground/run-worker-first/wrangler.toml new file mode 100644 index 000000000000..0653b834d6bb --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/wrangler.toml @@ -0,0 +1,4 @@ +name = "api" +main = "./middleware/index.ts" +compatibility_date = "2024-12-30" +assets = { not_found_handling = "single-page-application", binding = "ASSETS", run_worker_first = true } diff --git a/packages/vite-plugin-cloudflare/src/miniflare-options.ts b/packages/vite-plugin-cloudflare/src/miniflare-options.ts index 4421c9813dc1..0bed9b834a6b 100644 --- a/packages/vite-plugin-cloudflare/src/miniflare-options.ts +++ b/packages/vite-plugin-cloudflare/src/miniflare-options.ts @@ -219,9 +219,8 @@ export function getDevMiniflareOptions( bindings: { CONFIG: { has_user_worker: resolvedPluginConfig.type === "workers", - ...(typeof assetsConfig.run_worker_first === "boolean" && { - invoke_user_worker_ahead_of_assets: assetsConfig.run_worker_first, - }), + invoke_user_worker_ahead_of_assets: + assetsConfig?.run_worker_first ?? false, }, }, serviceBindings: { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fde1972e5378..a6e438da92a3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2567,6 +2567,43 @@ importers: specifier: workspace:* version: link:../../../wrangler + packages/vite-plugin-cloudflare/playground/run-worker-first: + dependencies: + react: + specifier: ^19.0.0 + version: 19.0.0 + react-dom: + specifier: ^19.0.0 + version: 19.0.0(react@19.0.0) + devDependencies: + '@cloudflare/vite-plugin': + specifier: workspace:* + version: link:../.. + '@cloudflare/workers-tsconfig': + specifier: workspace:* + version: link:../../../workers-tsconfig + '@cloudflare/workers-types': + specifier: ^4.20250310.0 + version: 4.20250424.0 + '@types/react': + specifier: ^19.0.0 + version: 19.0.7 + '@types/react-dom': + specifier: ^19.0.0 + version: 19.0.3(@types/react@19.0.7) + '@vitejs/plugin-react': + specifier: ^4.3.4 + version: 4.3.4(vite@6.1.0(@types/node@18.19.76)(jiti@2.4.2)(lightningcss@1.29.2)) + typescript: + specifier: catalog:default + version: 5.7.3 + vite: + specifier: catalog:vite-plugin + version: 6.1.0(@types/node@18.19.76)(jiti@2.4.2)(lightningcss@1.29.2) + wrangler: + specifier: workspace:* + version: link:../../../wrangler + packages/vite-plugin-cloudflare/playground/same-worker-service-bindings: devDependencies: '@cloudflare/vite-plugin': From 529e282549338f6770f66f07dcc7e51334851d1f Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Fri, 25 Apr 2025 10:22:28 +0100 Subject: [PATCH 4/8] switch run_worker_first playground to use wrangler.jsonc --- .../playground/run-worker-first/wrangler.jsonc | 10 ++++++++++ .../playground/run-worker-first/wrangler.toml | 4 ---- 2 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/wrangler.jsonc delete mode 100644 packages/vite-plugin-cloudflare/playground/run-worker-first/wrangler.toml diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/wrangler.jsonc b/packages/vite-plugin-cloudflare/playground/run-worker-first/wrangler.jsonc new file mode 100644 index 000000000000..d7eeee5d0ceb --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/wrangler.jsonc @@ -0,0 +1,10 @@ +{ + "name": "api", + "main": "./middleware/index.ts", + "compatibility_date": "2024-12-30", + "assets": { + "not_found_handling": "single-page-application", + "binding": "ASSETS", + "run_worker_first": true, + }, +} diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/wrangler.toml b/packages/vite-plugin-cloudflare/playground/run-worker-first/wrangler.toml deleted file mode 100644 index 0653b834d6bb..000000000000 --- a/packages/vite-plugin-cloudflare/playground/run-worker-first/wrangler.toml +++ /dev/null @@ -1,4 +0,0 @@ -name = "api" -main = "./middleware/index.ts" -compatibility_date = "2024-12-30" -assets = { not_found_handling = "single-page-application", binding = "ASSETS", run_worker_first = true } From 582a7512822fba5657167a45b5f7c6e21b4c097d Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Fri, 25 Apr 2025 10:29:40 +0100 Subject: [PATCH 5/8] remove unnecessary unit test --- .../__tests__/get-miniflare-options.spec.ts | 79 ------------------- 1 file changed, 79 deletions(-) delete mode 100644 packages/vite-plugin-cloudflare/src/__tests__/get-miniflare-options.spec.ts diff --git a/packages/vite-plugin-cloudflare/src/__tests__/get-miniflare-options.spec.ts b/packages/vite-plugin-cloudflare/src/__tests__/get-miniflare-options.spec.ts deleted file mode 100644 index ef22a428aff1..000000000000 --- a/packages/vite-plugin-cloudflare/src/__tests__/get-miniflare-options.spec.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { - afterAll, - afterEach, - beforeAll, - describe, - expect, - test, - vi, -} from "vitest"; -import { ROUTER_WORKER_NAME } from "../constants"; -import { getDevMiniflareOptions } from "../miniflare-options"; -import type { WorkerOptions } from "miniflare"; - -describe("getDevMiniflareOptions", () => { - beforeAll(() => { - vi.mock("fs"); - vi.mock("path"); - vi.mock("wrangler", () => ({ - unstable_getMiniflareWorkerOptions: vi.fn(() => ({ - externalWorkers: {}, - workerOptions: {}, - })), - })); - }); - afterEach(() => { - vi.resetAllMocks(); - }); - afterAll(() => { - vi.restoreAllMocks(); - }); - test.each([ - { run_worker_first: true }, - { run_worker_first: false }, - { run_worker_first: undefined }, - ])( - "Should consider run_worker_first=$run_worker_first flag", - ({ run_worker_first }) => { - // @ts-expect-error - const mf_options: { workers: WorkerOptions[] } = getDevMiniflareOptions( - { - type: "workers", - entryWorkerEnvironmentName: "test", - workers: { - // @ts-expect-error - test: { - assets: { - run_worker_first, - }, - }, - }, - }, - { config: { logLevel: "info" } }, - false - ); - expect(mf_options).toMatchObject({ workers: expect.any(Array) }); - const worker = mf_options.workers.find( - (worker) => worker.name === ROUTER_WORKER_NAME - ); - expect(worker).toBeDefined(); - if (run_worker_first === undefined) { - expect(worker).toMatchObject({ - bindings: { - CONFIG: expect.not.objectContaining({ - invoke_user_worker_ahead_of_assets: expect.anything(), - }), - }, - }); - } else { - expect(worker).toMatchObject({ - bindings: { - CONFIG: { - invoke_user_worker_ahead_of_assets: run_worker_first, - }, - }, - }); - } - } - ); -}); From 4e8eb8d96d93bfbedfaf8487b90f99e8bce26b1b Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Fri, 25 Apr 2025 10:53:05 +0100 Subject: [PATCH 6/8] move `failsIf()` helper into shared module --- .../playground/__test-utils__/index.ts | 6 ++++++ .../playground/react-spa/__tests__/assets.spec.ts | 6 +----- .../experimental-headers-and-redirects/assets.spec.ts | 6 +----- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/packages/vite-plugin-cloudflare/playground/__test-utils__/index.ts b/packages/vite-plugin-cloudflare/playground/__test-utils__/index.ts index ffc0462924a5..cc37aaf32e10 100644 --- a/packages/vite-plugin-cloudflare/playground/__test-utils__/index.ts +++ b/packages/vite-plugin-cloudflare/playground/__test-utils__/index.ts @@ -1,2 +1,8 @@ +import { test } from "vitest"; + export * from "../vitest-setup"; export * from "./responses"; + +export function failsIf(condition: boolean) { + return condition ? test.fails : test; +} diff --git a/packages/vite-plugin-cloudflare/playground/react-spa/__tests__/assets.spec.ts b/packages/vite-plugin-cloudflare/playground/react-spa/__tests__/assets.spec.ts index 262e57150a83..22f788be5895 100644 --- a/packages/vite-plugin-cloudflare/playground/react-spa/__tests__/assets.spec.ts +++ b/packages/vite-plugin-cloudflare/playground/react-spa/__tests__/assets.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "vitest"; -import { isBuild, page, viteTestUrl } from "../../__test-utils__"; +import { failsIf, isBuild, page, viteTestUrl } from "../../__test-utils__"; describe("react-spa", () => { test("returns the correct home page", async () => { @@ -65,7 +65,3 @@ describe("react-spa", () => { ); }); }); - -function failsIf(condition: boolean) { - return condition ? test.fails : test; -} diff --git a/packages/vite-plugin-cloudflare/playground/react-spa/__tests__/experimental-headers-and-redirects/assets.spec.ts b/packages/vite-plugin-cloudflare/playground/react-spa/__tests__/experimental-headers-and-redirects/assets.spec.ts index 377912476c52..6f4fa0b7b036 100644 --- a/packages/vite-plugin-cloudflare/playground/react-spa/__tests__/experimental-headers-and-redirects/assets.spec.ts +++ b/packages/vite-plugin-cloudflare/playground/react-spa/__tests__/experimental-headers-and-redirects/assets.spec.ts @@ -1,7 +1,7 @@ import { readFileSync, writeFileSync } from "node:fs"; import { join } from "node:path"; import { describe, expect, test, vi } from "vitest"; -import { isBuild, page, viteTestUrl } from "../../../__test-utils__"; +import { failsIf, isBuild, page, viteTestUrl } from "../../../__test-utils__"; describe( "react-spa (with experimental support)", @@ -115,7 +115,3 @@ describe("reloading the server", () => { } ); }); - -function failsIf(condition: boolean) { - return condition ? test.fails : test; -} From 4a887381fc967bb077fefb61cd6bd630ce8948b9 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Fri, 25 Apr 2025 10:53:20 +0100 Subject: [PATCH 7/8] clarify that only one tests will fail in `vite dev` mode --- .../run-worker-first/__tests__/run-worker-first.spec.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/vite-plugin-cloudflare/playground/run-worker-first/__tests__/run-worker-first.spec.ts b/packages/vite-plugin-cloudflare/playground/run-worker-first/__tests__/run-worker-first.spec.ts index 122b138a0807..a83df69766cb 100644 --- a/packages/vite-plugin-cloudflare/playground/run-worker-first/__tests__/run-worker-first.spec.ts +++ b/packages/vite-plugin-cloudflare/playground/run-worker-first/__tests__/run-worker-first.spec.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "vitest"; -import { isBuild, page, viteTestUrl } from "../../__test-utils__"; +import { failsIf, isBuild, page, viteTestUrl } from "../../__test-utils__"; -describe.skipIf(!isBuild)("run_worker_first support", () => { +describe("run_worker_first support", () => { test("returns the correct home page", async () => { const content = await page.textContent("h1"); expect(content).toBe("Vite + React"); @@ -25,7 +25,9 @@ describe.skipIf(!isBuild)("run_worker_first support", () => { expect(response.status).toBe(401); }); - test("returns UNAUTH for an admin image", async () => { + // This is the only use case that is not currently supported in dev mode. + // In that mode the middleware that runs the Worker is after the built-in Vite middleware that handles the assets. + failsIf(!isBuild)("returns UNAUTH for an admin image", async () => { const response = await fetch(viteTestUrl + "/admin/secret.svg"); expect(response.status).toBe(401); }); From ab82f46ec99d2585880d932d5b7b27e3203a1b98 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Fri, 25 Apr 2025 13:33:26 +0100 Subject: [PATCH 8/8] remove unnecessary change --- .changeset/all-doors-pick.md | 5 ----- packages/vite-plugin-cloudflare/src/miniflare-options.ts | 2 -- 2 files changed, 7 deletions(-) delete mode 100644 .changeset/all-doors-pick.md diff --git a/.changeset/all-doors-pick.md b/.changeset/all-doors-pick.md deleted file mode 100644 index 89301fbd2970..000000000000 --- a/.changeset/all-doors-pick.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@cloudflare/vite-plugin": patch ---- - -Do not ignore `run_worker_first` in `vite preview` mode. diff --git a/packages/vite-plugin-cloudflare/src/miniflare-options.ts b/packages/vite-plugin-cloudflare/src/miniflare-options.ts index 0bed9b834a6b..bb7a745b1aa8 100644 --- a/packages/vite-plugin-cloudflare/src/miniflare-options.ts +++ b/packages/vite-plugin-cloudflare/src/miniflare-options.ts @@ -219,8 +219,6 @@ export function getDevMiniflareOptions( bindings: { CONFIG: { has_user_worker: resolvedPluginConfig.type === "workers", - invoke_user_worker_ahead_of_assets: - assetsConfig?.run_worker_first ?? false, }, }, serviceBindings: {