Skip to content

Commit 4c509ec

Browse files
authored
Support containers on Vite auxiliary Workers (#10825)
* Support containers in auxiliary Vite Workers * Address typechecking * add changeset * typo
1 parent eb88d56 commit 4c509ec

File tree

7 files changed

+285
-283
lines changed

7 files changed

+285
-283
lines changed

.changeset/neat-eyes-roll.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+
Support containers defined for Vite auxiliary Workers
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name": "entry",
3+
"main": "./src/entry.ts",
4+
"compatibility_date": "2025-04-03",
5+
"services": [
6+
{
7+
"binding": "APP",
8+
"service": "container-app",
9+
},
10+
],
11+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default {
2+
async fetch(request, env): Promise<Response> {
3+
return env.APP.fetch(request);
4+
},
5+
} satisfies ExportedHandler<Env>;

packages/vite-plugin-cloudflare/playground/containers/vite.config.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,11 @@ import { cloudflare } from "@cloudflare/vite-plugin";
22
import { defineConfig } from "vite";
33

44
export default defineConfig({
5-
plugins: [cloudflare({ inspectorPort: false, persistState: false })],
5+
plugins: [
6+
cloudflare({
7+
persistState: false,
8+
configPath: "entry.wrangler.jsonc",
9+
auxiliaryWorkers: [{ configPath: "wrangler.jsonc" }],
10+
}),
11+
],
612
});
Lines changed: 3 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import assert from "node:assert";
21
import path from "node:path";
3-
import { prepareContainerImagesForDev } from "@cloudflare/containers-shared/src/images";
42
import { getDevContainerImageName } from "@cloudflare/containers-shared/src/knobs";
53
import { isDockerfile } from "@cloudflare/containers-shared/src/utils";
64
import type { WorkerConfig } from "./plugin-config";
@@ -22,20 +20,14 @@ export function getDockerPath(): string {
2220
* with image tag set to well-known dev format, or undefined if
2321
* containers are not enabled or not configured.
2422
*/
25-
async function getContainerOptions(options: {
23+
export function getContainerOptions(options: {
2624
containersConfig: WorkerConfig["containers"];
27-
isContainersEnabled: boolean;
2825
containerBuildId: string;
2926
configPath?: string;
3027
}) {
31-
const {
32-
containersConfig,
33-
isContainersEnabled,
34-
containerBuildId,
35-
configPath,
36-
} = options;
28+
const { containersConfig, containerBuildId, configPath } = options;
3729

38-
if (!containersConfig?.length || isContainersEnabled === false) {
30+
if (!containersConfig?.length) {
3931
return undefined;
4032
}
4133

@@ -64,60 +56,3 @@ async function getContainerOptions(options: {
6456
}
6557
});
6658
}
67-
68-
/**
69-
* Builds or pulls the container images for local development, and returns the
70-
* corresponding list of image tags
71-
*
72-
* @param options.containersConfig The configured containers
73-
* @param options.containerBuildId The container build id
74-
* @param options.isContainersEnabled Whether containers is enabled for this Worker
75-
* @param options.dockerPath The path to the Docker executable
76-
* @param options.configPath The path of the wrangler configuration file
77-
* @returns The list of image tags corresponding to the built/pulled container images
78-
*/
79-
export async function prepareContainerImages(options: {
80-
containersConfig: WorkerConfig["containers"];
81-
containerBuildId?: string;
82-
isContainersEnabled: boolean;
83-
dockerPath: string;
84-
configPath?: string;
85-
}): Promise<Set<string>> {
86-
assert(
87-
options.containerBuildId,
88-
"Build ID should be set if containers are enabled and defined"
89-
);
90-
91-
const {
92-
containersConfig,
93-
isContainersEnabled,
94-
dockerPath,
95-
containerBuildId,
96-
configPath,
97-
} = options;
98-
const uniqueImageTags = new Set<string>();
99-
100-
// Assemble container options and build if necessary
101-
const containerOptions = await getContainerOptions({
102-
containersConfig,
103-
containerBuildId,
104-
isContainersEnabled,
105-
configPath,
106-
});
107-
108-
if (containerOptions) {
109-
// keep track of them so we can clean up later
110-
for (const container of containerOptions) {
111-
uniqueImageTags.add(container.image_tag);
112-
}
113-
114-
await prepareContainerImagesForDev({
115-
dockerPath,
116-
containerOptions,
117-
onContainerImagePreparationStart: () => {},
118-
onContainerImagePreparationEnd: () => {},
119-
});
120-
}
121-
122-
return uniqueImageTags;
123-
}

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

Lines changed: 31 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import assert from "node:assert";
22
import * as util from "node:util";
3-
import {
4-
cleanupContainers,
5-
generateContainerBuildId,
6-
resolveDockerHost,
7-
} from "@cloudflare/containers-shared/src/utils";
3+
import { prepareContainerImagesForDev } from "@cloudflare/containers-shared";
4+
import { cleanupContainers } from "@cloudflare/containers-shared/src/utils";
85
import { generateStaticRoutingRuleMatcher } from "@cloudflare/workers-shared/asset-worker/src/utils/rules-engine";
96
import { CoreHeaders, Miniflare } from "miniflare";
107
import colors from "picocolors";
@@ -21,7 +18,7 @@ import {
2118
kRequestType,
2219
ROUTER_WORKER_NAME,
2320
} from "./constants";
24-
import { getDockerPath, prepareContainerImages } from "./containers";
21+
import { getDockerPath } from "./containers";
2522
import {
2623
addDebugToVitePrintUrls,
2724
DEBUG_PATH,
@@ -234,23 +231,14 @@ export function cloudflare(pluginConfig: PluginConfig = {}): vite.Plugin[] {
234231
const entryWorkerConfig = getEntryWorkerConfig(
235232
ctx.resolvedPluginConfig
236233
);
237-
const hasDevContainers =
238-
entryWorkerConfig?.containers?.length &&
239-
entryWorkerConfig.dev.enable_containers;
240-
const dockerPath = getDockerPath();
241-
242-
if (hasDevContainers) {
243-
containerBuildId = generateContainerBuildId();
244-
entryWorkerConfig.dev.container_engine =
245-
resolveDockerHost(dockerPath);
246-
}
247234

248-
const miniflareDevOptions = await getDevMiniflareOptions({
249-
resolvedPluginConfig: ctx.resolvedPluginConfig,
250-
viteDevServer,
251-
inspectorPort: inputInspectorPort,
252-
containerBuildId,
253-
});
235+
const { config: miniflareDevOptions, allContainerOptions } =
236+
await getDevMiniflareOptions({
237+
resolvedPluginConfig: ctx.resolvedPluginConfig,
238+
viteDevServer,
239+
inspectorPort: inputInspectorPort,
240+
containerBuildId,
241+
});
254242

255243
if (!miniflare) {
256244
debuglog("Creating new Miniflare instance");
@@ -318,21 +306,22 @@ export function cloudflare(pluginConfig: PluginConfig = {}): vite.Plugin[] {
318306
};
319307
}
320308

321-
if (hasDevContainers) {
309+
if (allContainerOptions.size > 0) {
322310
viteDevServer.config.logger.info(
323311
colors.dim(
324312
colors.yellow(
325313
"∷ Building container images for local development...\n"
326314
)
327315
)
328316
);
329-
containerImageTagsSeen = await prepareContainerImages({
330-
containersConfig: entryWorkerConfig.containers,
331-
containerBuildId,
332-
isContainersEnabled: entryWorkerConfig.dev.enable_containers,
333-
dockerPath,
334-
configPath: entryWorkerConfig.configPath,
317+
await prepareContainerImagesForDev({
318+
dockerPath: getDockerPath(),
319+
containerOptions: [...allContainerOptions.values()],
320+
onContainerImagePreparationStart: () => {},
321+
onContainerImagePreparationEnd: () => {},
335322
});
323+
324+
containerImageTagsSeen = new Set(allContainerOptions.keys());
336325
viteDevServer.config.logger.info(
337326
colors.dim(
338327
colors.yellow(
@@ -356,8 +345,8 @@ export function cloudflare(pluginConfig: PluginConfig = {}): vite.Plugin[] {
356345
*
357346
*/
358347
process.on("exit", async () => {
359-
if (containerImageTagsSeen.size) {
360-
cleanupContainers(dockerPath, containerImageTagsSeen);
348+
if (allContainerOptions.size > 0) {
349+
cleanupContainers(getDockerPath(), containerImageTagsSeen);
361350
}
362351
});
363352
}
@@ -415,27 +404,15 @@ export function cloudflare(pluginConfig: PluginConfig = {}): vite.Plugin[] {
415404
vitePreviewServer
416405
);
417406

418-
// first Worker in the Array is always the entry Worker
419-
const entryWorkerConfig = ctx.resolvedPluginConfig.workers[0];
420-
const hasDevContainers =
421-
entryWorkerConfig?.containers?.length &&
422-
entryWorkerConfig.dev.enable_containers;
423-
let containerBuildId: string | undefined;
424-
425-
if (hasDevContainers) {
426-
containerBuildId = generateContainerBuildId();
427-
}
428-
429-
miniflare = new Miniflare(
407+
const { config: miniflareOptions, allContainerOptions } =
430408
await getPreviewMiniflareOptions({
431409
resolvedPluginConfig: ctx.resolvedPluginConfig,
432410
vitePreviewServer,
433411
inspectorPort: inputInspectorPort,
434-
containerBuildId,
435-
})
436-
);
412+
});
413+
miniflare = new Miniflare(miniflareOptions);
437414

438-
if (hasDevContainers) {
415+
if (allContainerOptions.size > 0) {
439416
const dockerPath = getDockerPath();
440417

441418
vitePreviewServer.config.logger.info(
@@ -445,13 +422,14 @@ export function cloudflare(pluginConfig: PluginConfig = {}): vite.Plugin[] {
445422
)
446423
)
447424
);
448-
containerImageTagsSeen = await prepareContainerImages({
449-
containersConfig: entryWorkerConfig.containers,
450-
containerBuildId,
451-
isContainersEnabled: entryWorkerConfig.dev.enable_containers,
452-
dockerPath,
453-
configPath: entryWorkerConfig.configPath,
425+
await prepareContainerImagesForDev({
426+
dockerPath: getDockerPath(),
427+
containerOptions: [...allContainerOptions.values()],
428+
onContainerImagePreparationStart: () => {},
429+
onContainerImagePreparationEnd: () => {},
454430
});
431+
containerImageTagsSeen = new Set(allContainerOptions.keys());
432+
455433
vitePreviewServer.config.logger.info(
456434
colors.dim(colors.yellow("\n⚡️ Containers successfully built.\n"))
457435
);

0 commit comments

Comments
 (0)