Skip to content

Commit 228ba99

Browse files
ensure vite-plugin disposes of miniflare
1 parent 66edd2f commit 228ba99

File tree

3 files changed

+46
-14
lines changed

3 files changed

+46
-14
lines changed

.changeset/shaky-socks-raise.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@cloudflare/vite-plugin": patch
3+
---
4+
5+
fix: vite-plugin now disposes its miniflare instance when closing down

packages/vite-plugin-cloudflare/playground/vitest-setup.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@ import {
99
preview,
1010
Rollup,
1111
} from "vite";
12-
import { beforeAll, beforeEach, inject } from "vitest";
12+
import { afterAll, beforeAll, beforeEach, inject } from "vitest";
1313
import type * as http from "node:http";
1414
import type { Browser, Page } from "playwright-chromium";
1515
import type {
1616
ConfigEnv,
1717
InlineConfig,
1818
Logger,
1919
PluginOption,
20+
PreviewServer,
2021
ResolvedConfig,
2122
UserConfig,
2223
ViteDevServer,
@@ -28,7 +29,7 @@ export const workspaceRoot = path.resolve(__dirname, "../");
2829
export const isBuild = !!process.env.VITE_TEST_BUILD;
2930
export const isWindows = process.platform === "win32";
3031

31-
let server: ViteDevServer | http.Server;
32+
let server: ViteDevServer | http.Server | PreviewServer;
3233

3334
/**
3435
* Vite Dev Server when testing serve
@@ -157,7 +158,7 @@ beforeAll(async (s) => {
157158
viteTestUrl = mod.viteTestUrl ?? viteTestUrl;
158159
}
159160
} else {
160-
await startDefaultServe();
161+
server = await startDefaultServe();
161162
}
162163
}
163164
} catch (e) {
@@ -166,10 +167,13 @@ beforeAll(async (s) => {
166167
// If the page remains open, a command like `await page.click(...)` produces
167168
// a timeout with an exception that hides the real error in the console.
168169
await page.close();
169-
await server?.close();
170170
throw e;
171171
}
172172

173+
afterAll(async () => {
174+
await server.close();
175+
});
176+
173177
return async () => {
174178
resetServerLogs();
175179

@@ -249,7 +253,7 @@ export async function loadConfig(configEnv: ConfigEnv) {
249253
}
250254

251255
export async function startDefaultServe(): Promise<
252-
ViteDevServer | http.Server
256+
ViteDevServer | http.Server | PreviewServer
253257
> {
254258
setupConsoleWarnCollector(serverLogs.warns);
255259

@@ -299,6 +303,7 @@ export async function startDefaultServe(): Promise<
299303
if (previewServer.config.base === "/") {
300304
viteTestUrl = viteTestUrl.replace(/\/$/, "");
301305
}
306+
server = previewServer;
302307
await page.goto(viteTestUrl);
303308
}
304309
return server;

packages/vite-plugin-cloudflare/src/index.ts

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,15 @@ export function cloudflare(pluginConfig: PluginConfig = {}): vite.Plugin[] {
8888
// This is set when the client environment is built to determine if the entry Worker should include assets
8989
let hasClientBuild = false;
9090

91+
// This is needed so that we can tell the difference between the Vite http server closing and restarting.
92+
let previousServer: unknown;
93+
let restartingServer = false;
94+
function updateRestartingServerFlag(viteDevServer: unknown) {
95+
restartingServer =
96+
previousServer !== undefined && viteDevServer !== previousServer;
97+
previousServer = viteDevServer;
98+
}
99+
91100
return [
92101
{
93102
name: "vite-plugin-cloudflare",
@@ -332,7 +341,20 @@ export function cloudflare(pluginConfig: PluginConfig = {}): vite.Plugin[] {
332341
return [];
333342
}
334343
},
344+
buildEnd() {
345+
if (!restartingServer) {
346+
miniflare?.dispose().catch((error) => {
347+
console.error("Error disposing Miniflare instance:", error);
348+
});
349+
miniflare = undefined;
350+
}
351+
// Reset the flag so that if a `buildEnd` hook is called again before the next
352+
// configureServer hook then we do dispose of miniflare correctly.
353+
restartingServer = false;
354+
},
335355
async configureServer(viteDevServer) {
356+
updateRestartingServerFlag(viteDevServer);
357+
336358
const inputInspectorPort = await getInputInspectorPortOption(
337359
pluginConfig,
338360
viteDevServer
@@ -399,6 +421,8 @@ export function cloudflare(pluginConfig: PluginConfig = {}): vite.Plugin[] {
399421
};
400422
},
401423
async configurePreviewServer(vitePreviewServer) {
424+
updateRestartingServerFlag(vitePreviewServer);
425+
402426
const workerConfigs = getWorkerConfigs(
403427
vitePreviewServer.config.root,
404428
pluginConfig.experimental?.mixedMode ?? false
@@ -409,7 +433,7 @@ export function cloudflare(pluginConfig: PluginConfig = {}): vite.Plugin[] {
409433
vitePreviewServer
410434
);
411435

412-
const miniflare = new Miniflare(
436+
miniflare = new Miniflare(
413437
await getPreviewMiniflareOptions(
414438
vitePreviewServer,
415439
workerConfigs,
@@ -419,19 +443,17 @@ export function cloudflare(pluginConfig: PluginConfig = {}): vite.Plugin[] {
419443
)
420444
);
421445

422-
handleWebSocket(
423-
vitePreviewServer.httpServer,
424-
() => miniflare.dispatchFetch
425-
);
446+
const dispatchFetch = miniflare.dispatchFetch;
447+
448+
handleWebSocket(vitePreviewServer.httpServer, () => dispatchFetch);
426449

427450
// In preview mode we put our middleware at the front of the chain so that all assets are handled in Miniflare
428451
vitePreviewServer.middlewares.use(async (req, res, next) => {
429452
try {
430453
const request = createRequest(req, res);
431-
const response = await miniflare.dispatchFetch(
432-
toMiniflareRequest(request),
433-
{ redirect: "manual" }
434-
);
454+
const response = await dispatchFetch(toMiniflareRequest(request), {
455+
redirect: "manual",
456+
});
435457

436458
// Vite uses HTTP/2 when `preview.https` is enabled
437459
if (req.httpVersionMajor === 2) {

0 commit comments

Comments
 (0)