From b8110aa1ca48574fc1eadb07ce0c1c2193bbc402 Mon Sep 17 00:00:00 2001 From: Aron Carroll Date: Tue, 3 Mar 2026 15:34:07 +0000 Subject: [PATCH 1/2] Add experimental.additionalPlugins support to the cloudflare() vite plugin --- packages/vite-plugin-cloudflare/src/index.ts | 7 +++++++ packages/vite-plugin-cloudflare/src/plugin-config.ts | 3 +++ 2 files changed, 10 insertions(+) diff --git a/packages/vite-plugin-cloudflare/src/index.ts b/packages/vite-plugin-cloudflare/src/index.ts index 9a07b9c4754..001c7577681 100644 --- a/packages/vite-plugin-cloudflare/src/index.ts +++ b/packages/vite-plugin-cloudflare/src/index.ts @@ -26,9 +26,11 @@ import type { PluginConfig } from "./plugin-config"; import type * as vite from "vite"; export { getLocalWorkerdCompatibilityDate } from "@cloudflare/workers-utils"; +export { createPlugin } from "./utils"; export type { PluginConfig } from "./plugin-config"; export type { WorkerConfig } from "./workers-configs"; +export type { PluginContext } from "./context"; const sharedContext: SharedContext = { hasShownWorkerConfigWarnings: false, @@ -47,6 +49,10 @@ await assertWranglerVersion(); export function cloudflare(pluginConfig: PluginConfig = {}): vite.Plugin[] { const ctx = new PluginContext(sharedContext); + const additionalPlugins = ( + pluginConfig.experimental?.additionalPlugins ?? [] + ).map((pluginFactory) => pluginFactory(ctx)); + return [ { name: "vite-plugin-cloudflare", @@ -90,5 +96,6 @@ export function cloudflare(pluginConfig: PluginConfig = {}): vite.Plugin[] { nodeJsAlsPlugin(ctx), nodeJsCompatPlugin(ctx), nodeJsCompatWarningsPlugin(ctx), + ...additionalPlugins, ]; } diff --git a/packages/vite-plugin-cloudflare/src/plugin-config.ts b/packages/vite-plugin-cloudflare/src/plugin-config.ts index 139a0f85223..4f27ad2fbfc 100644 --- a/packages/vite-plugin-cloudflare/src/plugin-config.ts +++ b/packages/vite-plugin-cloudflare/src/plugin-config.ts @@ -11,6 +11,7 @@ import { readWorkerConfigFromFile, resolveWorkerType, } from "./workers-configs"; +import type { PluginContext } from "./context"; import type { Defined } from "./utils"; import type { AssetsOnlyWorkerResolvedConfig, @@ -51,6 +52,8 @@ interface Experimental { headersAndRedirectsDevModeSupport?: boolean; /** Experimental support for a dedicated prerender Worker */ prerenderWorker?: AuxiliaryWorkerConfig; + /** Experimental support for extending the cloudflare plugin with additional Vite plugins. */ + additionalPlugins?: ((ctx: PluginContext) => vite.Plugin)[]; } type FilteredEntryWorkerConfig = Omit< From 5a15f9823bec098d47c315901fc1fb3e1367af73 Mon Sep 17 00:00:00 2001 From: Aron Carroll Date: Tue, 3 Mar 2026 15:52:20 +0000 Subject: [PATCH 2/2] Add test to verify experimental plugins work --- .../experimental-plugins/static.spec.ts | 19 +++++++++++ .../vite.config.experimental-plugins.ts | 34 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 packages/vite-plugin-cloudflare/playground/static/__tests__/experimental-plugins/static.spec.ts create mode 100644 packages/vite-plugin-cloudflare/playground/static/vite.config.experimental-plugins.ts diff --git a/packages/vite-plugin-cloudflare/playground/static/__tests__/experimental-plugins/static.spec.ts b/packages/vite-plugin-cloudflare/playground/static/__tests__/experimental-plugins/static.spec.ts new file mode 100644 index 00000000000..feee51b8b52 --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/static/__tests__/experimental-plugins/static.spec.ts @@ -0,0 +1,19 @@ +import { test } from "vitest"; +import { fetchJson, page, viteTestUrl } from "../../../__test-utils__"; + +test("returns the correct home page", async ({ expect }) => { + const content = await page.textContent("h1"); + expect(content).toBe("Vite + TypeScript"); +}); + +test("returns the correct response from the API", async ({ expect }) => { + const result = await fetchJson("/api/"); + expect(result).toEqual({ name: "Cloudflare" }); +}); + +test("returns the correct response from the experimental plugin", async ({ expect }) => { + const response = await fetch(`${viteTestUrl}/__experimental-plugin-test`); + expect(response.status).toBe(200); + const result = await response.json(); + expect(result).toEqual({ hasMiniflare: true, type: "workers" }); +}); diff --git a/packages/vite-plugin-cloudflare/playground/static/vite.config.experimental-plugins.ts b/packages/vite-plugin-cloudflare/playground/static/vite.config.experimental-plugins.ts new file mode 100644 index 00000000000..2679f4764fc --- /dev/null +++ b/packages/vite-plugin-cloudflare/playground/static/vite.config.experimental-plugins.ts @@ -0,0 +1,34 @@ +import { cloudflare, createPlugin } from "@cloudflare/vite-plugin"; +import { defineConfig } from "vite"; + +export default defineConfig({ + plugins: [ + cloudflare({ + configPath: "./wrangler.with-api.jsonc", + inspectorPort: false, + persistState: false, + experimental: { + additionalPlugins: [ + createPlugin("test-plugin", (ctx) => ({ + configureServer(server) { + server.middlewares.use((req, res, next) => { + if (req.url === "/__experimental-plugin-test") { + const config = ctx.resolvedPluginConfig; + res.setHeader("Content-Type", "application/json"); + res.end( + JSON.stringify({ + type: config.type, + hasMiniflare: ctx.miniflare !== undefined, + }) + ); + return; + } + next(); + }); + }, + })), + ], + }, + }), + ], +});