From 91ca74fbd53a8bb32d3f29d1a50640478bd1da1e Mon Sep 17 00:00:00 2001 From: James Opstad <13586373+jamesopstad@users.noreply.github.com> Date: Fri, 13 Dec 2024 09:18:46 +0000 Subject: [PATCH] Allow output directories to be overridden (#110) * Made output directories overridable * Added output directory tests --- .../src/cloudflare-environment.ts | 3 -- packages/vite-plugin-cloudflare/src/index.ts | 11 ++--- .../src/miniflare-options.ts | 41 +++++++++++-------- playground/multi-worker/.gitignore | 1 + .../multi-worker/__tests__/basic.spec.ts | 9 ---- .../multi-worker.spec.ts | 20 +++++++++ ...-bindings.spec.ts => multi-worker.spec.ts} | 18 +++++++- playground/multi-worker/package.json | 4 +- playground/multi-worker/tsconfig.node.json | 6 ++- .../vite.config.custom-output-directories.ts | 19 +++++++++ 10 files changed, 93 insertions(+), 39 deletions(-) create mode 100644 playground/multi-worker/.gitignore delete mode 100644 playground/multi-worker/__tests__/basic.spec.ts create mode 100644 playground/multi-worker/__tests__/custom-output-directories/multi-worker.spec.ts rename playground/multi-worker/__tests__/{service-bindings.spec.ts => multi-worker.spec.ts} (56%) create mode 100644 playground/multi-worker/vite.config.custom-output-directories.ts diff --git a/packages/vite-plugin-cloudflare/src/cloudflare-environment.ts b/packages/vite-plugin-cloudflare/src/cloudflare-environment.ts index c4d93fc2..33bcd8a5 100644 --- a/packages/vite-plugin-cloudflare/src/cloudflare-environment.ts +++ b/packages/vite-plugin-cloudflare/src/cloudflare-environment.ts @@ -124,7 +124,6 @@ const cloudflareBuiltInModules = [ export function createCloudflareEnvironmentOptions( workerConfig: WorkerConfig, - userConfig: vite.UserConfig, ): vite.EnvironmentOptions { return { resolve: { @@ -143,8 +142,6 @@ export function createCloudflareEnvironmentOptions( createEnvironment(name, config) { return new vite.BuildEnvironment(name, config); }, - // This is a bit of a hack to make sure the user can't override the output directory at the environment level - outDir: userConfig.build?.outDir ?? 'dist', ssr: true, rollupOptions: { // Note: vite starts dev pre-bundling crawling from either optimizeDeps.entries or rollupOptions.input diff --git a/packages/vite-plugin-cloudflare/src/index.ts b/packages/vite-plugin-cloudflare/src/index.ts index af7ff84e..80366a24 100644 --- a/packages/vite-plugin-cloudflare/src/index.ts +++ b/packages/vite-plugin-cloudflare/src/index.ts @@ -44,10 +44,7 @@ export function cloudflare(pluginConfig: PluginConfig = {}): vite.Plugin { ([environmentName, workerConfig]) => { return [ environmentName, - createCloudflareEnvironmentOptions( - workerConfig, - userConfig, - ), + createCloudflareEnvironmentOptions(workerConfig), ]; }, ), @@ -93,12 +90,10 @@ export function cloudflare(pluginConfig: PluginConfig = {}): vite.Plugin { }; }, configEnvironment(name, options) { - if (resolvedPluginConfig.type === 'workers') { + if (resolvedPluginConfig.type === 'workers' && !options.build?.outDir) { options.build = { ...options.build, - // Puts all environment builds in subdirectories of the same build directory - // TODO: allow the user to override this - outDir: path.join(options.build?.outDir ?? 'dist', name), + outDir: path.join('dist', name), }; } }, diff --git a/packages/vite-plugin-cloudflare/src/miniflare-options.ts b/packages/vite-plugin-cloudflare/src/miniflare-options.ts index d17feeab..3a941204 100644 --- a/packages/vite-plugin-cloudflare/src/miniflare-options.ts +++ b/packages/vite-plugin-cloudflare/src/miniflare-options.ts @@ -403,6 +403,19 @@ export function getDevMiniflareOptions( }; } +function getConfigPath( + viteConfig: vite.ResolvedConfig, + environmentName: string, +) { + const outDir = viteConfig.environments[environmentName]?.build.outDir; + + assert(outDir, `No output directory for environment ${environmentName}`); + + const configPath = path.resolve(viteConfig.root, outDir, 'wrangler.json'); + + return configPath; +} + function getEntryModule(main: string | undefined) { assert( main, @@ -419,19 +432,19 @@ export function getPreviewMiniflareOptions( vitePreviewServer: vite.PreviewServer, ): MiniflareOptions { const viteConfig = vitePreviewServer.config; - // For now, we are enforcing that packages are always inside the same build directory - const buildDirectory = path.resolve(viteConfig.root, viteConfig.build.outDir); - const configPath = - resolvedPluginConfig.type === 'workers' - ? path.join( - buildDirectory, - resolvedPluginConfig.entryWorkerEnvironmentName, - 'wrangler.json', - ) - : path.join(buildDirectory, 'wrangler.json'); const configs = [ - unstable_readConfig({ config: configPath }, {}), + unstable_readConfig( + { + config: getConfigPath( + viteConfig, + resolvedPluginConfig.type === 'workers' + ? resolvedPluginConfig.entryWorkerEnvironmentName + : 'client', + ), + }, + {}, + ), ...(resolvedPluginConfig.type === 'workers' ? Object.keys(resolvedPluginConfig.workers) .filter( @@ -442,11 +455,7 @@ export function getPreviewMiniflareOptions( .map((environmentName) => unstable_readConfig( { - config: path.join( - buildDirectory, - environmentName, - 'wrangler.json', - ), + config: getConfigPath(viteConfig, environmentName), }, {}, ), diff --git a/playground/multi-worker/.gitignore b/playground/multi-worker/.gitignore new file mode 100644 index 00000000..05735bfe --- /dev/null +++ b/playground/multi-worker/.gitignore @@ -0,0 +1 @@ +custom-output-directory \ No newline at end of file diff --git a/playground/multi-worker/__tests__/basic.spec.ts b/playground/multi-worker/__tests__/basic.spec.ts deleted file mode 100644 index eef76d91..00000000 --- a/playground/multi-worker/__tests__/basic.spec.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { describe, expect, test } from 'vitest'; -import { getJsonResponse } from '../../__test-utils__'; - -describe('multi-worker basic functionality', async () => { - test('entry worker returns a response', async () => { - const result = await getJsonResponse(); - expect(result).toEqual({ name: 'Worker A' }); - }); -}); diff --git a/playground/multi-worker/__tests__/custom-output-directories/multi-worker.spec.ts b/playground/multi-worker/__tests__/custom-output-directories/multi-worker.spec.ts new file mode 100644 index 00000000..0ada1b03 --- /dev/null +++ b/playground/multi-worker/__tests__/custom-output-directories/multi-worker.spec.ts @@ -0,0 +1,20 @@ +import * as fs from 'node:fs'; +import * as path from 'node:path'; +import { describe, expect, test } from 'vitest'; +import { getJsonResponse, isBuild, rootDir } from '../../../__test-utils__'; + +describe.runIf(isBuild)('output directories', () => { + test('creates the correct output directories', () => { + expect(fs.existsSync(path.join(rootDir, 'dist', 'worker_a'))).toBe(true); + expect(fs.existsSync(path.join(rootDir, 'custom-output-directory'))).toBe( + true, + ); + }); +}); + +describe('multi-worker service bindings', async () => { + test('returns a response from another worker', async () => { + const result = await getJsonResponse('/fetch'); + expect(result).toEqual({ result: { name: 'Worker B' } }); + }); +}); diff --git a/playground/multi-worker/__tests__/service-bindings.spec.ts b/playground/multi-worker/__tests__/multi-worker.spec.ts similarity index 56% rename from playground/multi-worker/__tests__/service-bindings.spec.ts rename to playground/multi-worker/__tests__/multi-worker.spec.ts index c9a2c2a2..fcbed2f4 100644 --- a/playground/multi-worker/__tests__/service-bindings.spec.ts +++ b/playground/multi-worker/__tests__/multi-worker.spec.ts @@ -1,5 +1,21 @@ +import * as fs from 'node:fs'; +import * as path from 'node:path'; import { describe, expect, test } from 'vitest'; -import { getJsonResponse } from '../../__test-utils__'; +import { getJsonResponse, isBuild, rootDir } from '../../__test-utils__'; + +describe.runIf(isBuild)('output directories', () => { + test('creates the correct output directories', () => { + expect(fs.existsSync(path.join(rootDir, 'dist', 'worker_a'))).toBe(true); + expect(fs.existsSync(path.join(rootDir, 'dist', 'worker_b'))).toBe(true); + }); +}); + +describe('multi-worker basic functionality', async () => { + test('entry worker returns a response', async () => { + const result = await getJsonResponse(); + expect(result).toEqual({ name: 'Worker A' }); + }); +}); describe('multi-worker service bindings', async () => { test('returns a response from another worker', async () => { diff --git a/playground/multi-worker/package.json b/playground/multi-worker/package.json index e32fbabc..4981bc9b 100644 --- a/playground/multi-worker/package.json +++ b/playground/multi-worker/package.json @@ -4,9 +4,11 @@ "type": "module", "scripts": { "build": "vite build --app", + "build:custom-output-directories": "vite build --app -c ./vite.config.custom-output-directories.ts", "check:types": "tsc --build", "dev": "vite dev", - "preview": "vite preview" + "preview": "vite preview", + "preview:custom-output-directories": "vite preview -c ./vite.config.custom-output-directories.ts" }, "devDependencies": { "@cloudflare/workers-types": "catalog:default", diff --git a/playground/multi-worker/tsconfig.node.json b/playground/multi-worker/tsconfig.node.json index c24133da..523e78a9 100644 --- a/playground/multi-worker/tsconfig.node.json +++ b/playground/multi-worker/tsconfig.node.json @@ -1,4 +1,8 @@ { "extends": ["@vite-plugin-cloudflare/typescript-config/base.json"], - "include": ["vite.config.ts", "__tests__"] + "include": [ + "vite.config.ts", + "vite.config.custom-output-directories.ts", + "__tests__" + ] } diff --git a/playground/multi-worker/vite.config.custom-output-directories.ts b/playground/multi-worker/vite.config.custom-output-directories.ts new file mode 100644 index 00000000..9e230ca5 --- /dev/null +++ b/playground/multi-worker/vite.config.custom-output-directories.ts @@ -0,0 +1,19 @@ +import { cloudflare } from '@flarelabs-net/vite-plugin-cloudflare'; +import { defineConfig } from 'vite'; + +export default defineConfig({ + environments: { + worker_b: { + build: { + outDir: 'custom-output-directory', + }, + }, + }, + plugins: [ + cloudflare({ + configPath: './worker-a/wrangler.toml', + auxiliaryWorkers: [{ configPath: './worker-b/wrangler.toml' }], + persistState: false, + }), + ], +});