Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
38aeee3
Install Vite plugin to vite projects in autoconfig
dario-piotrowicz Dec 2, 2025
c1dfe61
In autoconfig consider vite projects using the vite plugin as already…
dario-piotrowicz Dec 3, 2025
d295673
add e2e tests
dario-piotrowicz Dec 3, 2025
f1f5cc4
update tests
dario-piotrowicz Dec 3, 2025
09415a8
remove unnecessary assets wrangler config
dario-piotrowicz Dec 3, 2025
60b1a3b
fix formatting
dario-piotrowicz Dec 3, 2025
dd1bfe6
fix tests type issues
dario-piotrowicz Dec 3, 2025
ec93039
remove e2e fixtures from linting
dario-piotrowicz Dec 3, 2025
1d17517
add `single-page-application` `not_found_handling` configuration
dario-piotrowicz Dec 3, 2025
a9f5ef6
Update packages/wrangler/src/autoconfig/frameworks/utils/vite-config.ts
dario-piotrowicz Dec 3, 2025
65e3fd8
Apply suggestions from code review
dario-piotrowicz Dec 3, 2025
d9e1087
Update packages/wrangler/src/autoconfig/frameworks/utils/vite-config.ts
dario-piotrowicz Dec 3, 2025
4b3c5b4
remove wrangler e2e and test React with C3, also add React in the c3 …
dario-piotrowicz Dec 4, 2025
fe001bc
remove barrel file
dario-piotrowicz Dec 4, 2025
f5fb88b
make `isConfigured` sync
dario-piotrowicz Dec 4, 2025
6200058
remove setup.test.ts file
dario-piotrowicz Dec 4, 2025
a1f8a20
remove involutary change
dario-piotrowicz Dec 4, 2025
1dfb57a
remove duplicated entry
dario-piotrowicz Dec 4, 2025
bc6fc76
fix incorrect verify check
dario-piotrowicz Dec 4, 2025
d0ff5d4
update changeset
dario-piotrowicz Dec 4, 2025
11c2371
add incompatibleVitePlugins option to transformViteConfig and also us…
dario-piotrowicz Dec 4, 2025
698d855
Update .changeset/petite-swans-train.md
dario-piotrowicz Dec 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/old-boxes-find.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wrangler": minor
---

Wrangler will no longer try to add additional configuration to projects using `@cloudflare/vite-plugin` when deploying or running `wrangler setup`
5 changes: 5 additions & 0 deletions .changeset/petite-swans-train.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wrangler": minor
---

When a Vite project is detected, install `@cloudflare/vite-plugin`
37 changes: 37 additions & 0 deletions packages/create-cloudflare/e2e/helpers/framework-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,43 @@ export async function verifyTypes(
}
}

export async function verifyCloudflareVitePluginConfigured(
{ verifyCloudflareVitePluginConfigured: verify }: FrameworkTestConfig,
projectPath: string,
) {
if (!verify) {
return;
}

const viteConfigTsPAth = join(projectPath, `vite.config.ts`);
const viteConfigJsPath = join(projectPath, `vite.config.js`);

let viteConfigPath: string;

if (existsSync(viteConfigTsPAth)) {
viteConfigPath = viteConfigTsPAth;
} else if (existsSync(viteConfigJsPath)) {
viteConfigPath = viteConfigJsPath;
} else {
throw new Error("Could not find Vite config file to modify");
}

const prePackageJson = JSON.parse(
readFile(join(projectPath, "package.json")),
) as { devDependencies: Record<string, string> };

expect(
prePackageJson.devDependencies?.["@cloudflare/vite-plugin"],
).not.toBeUndefined();

const viteConfig = readFile(viteConfigPath);

expect(viteConfig).toContain(
'import { cloudflare } from "@cloudflare/vite-plugin"',
);
expect(viteConfig).toMatch(/plugins:\s*?\[.*?cloudflare.*?]/);
}

export function shouldRunTest(testConfig: FrameworkTestConfig) {
return (
// Skip if the test is quarantined
Expand Down
6 changes: 5 additions & 1 deletion packages/create-cloudflare/e2e/helpers/run-c3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,13 @@ export type RunnerConfig = {
};
};
/**
* Specifies whether to verify generated types for the project
* Specifies whether to verify generated types for the project.
*/
verifyTypes?: boolean;
/**
* Verifies whether the Cloudflare Vite plugin has been installed and configured.
*/
verifyCloudflareVitePluginConfigured?: boolean;
};

export const runC3 = async (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
runC3ForFrameworkTest,
shouldRunTest,
testGitCommitMessage,
verifyCloudflareVitePluginConfigured,
verifyDeployment,
verifyDevScript,
verifyPreviewScript,
Expand Down Expand Up @@ -150,6 +151,11 @@ describe
);

await verifyTypes(testConfig, frameworkConfig, project.path);

await verifyCloudflareVitePluginConfigured(
testConfig,
project.path,
);
} catch (e) {
expect.fail(
"Failed due to an exception while running C3. See logs for more details. Error: " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -865,6 +865,7 @@ function getExperimentalFrameworkTestConfig(
},
nodeCompat: false,
verifyTypes: false,
verifyCloudflareVitePluginConfigured: true,
},
{
name: "react-router",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ describe("autoconfig details - confirmAutoConfigDetails()", () => {
workerName: "my-astro-site",
buildCommand: "astro build",
framework: {
configured: false,
isConfigured: () => false,
configure: () => ({ wranglerConfig: {} }),
name: "astro",
},
Expand All @@ -116,7 +116,7 @@ describe("autoconfig details - confirmAutoConfigDetails()", () => {
"configured": false,
"framework": Object {
"configure": [Function],
"configured": false,
"isConfigured": [Function],
"name": "astro",
},
"outputDir": "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ describe("autoconfig details - displayAutoConfigDetails()", () => {
workerName: "my-astro-app",
framework: {
name: "Astro",
configured: false,
isConfigured: () => false,
configure: () => ({ wranglerConfig: {} }),
},
buildCommand: "astro build",
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/__tests__/autoconfig/run.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ describe("autoconfig (deploy)", () => {
framework: {
name: "Fake",
configure: configureSpy,
isConfigured: () => false,
} as unknown as Framework,
outputDir: "dist",
packageJson: {
Expand Down
2 changes: 1 addition & 1 deletion packages/wrangler/src/autoconfig/details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ export async function getDetailsForAutoConfig({

return {
projectPath: projectPath,
configured: framework?.configured ?? false,
configured: framework?.isConfigured(projectPath) ?? false,
framework,
packageJson,
buildCommand: detectedFramework?.buildCommand ?? packageJsonBuild,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { SolidStart } from "./solid-start";
import { Static } from "./static";
import { SvelteKit } from "./sveltekit";
import { TanstackStart } from "./tanstack";
import { Vite } from "./vite";
import type { Framework } from ".";

export function getFramework(detectedFramework?: {
Expand All @@ -27,6 +28,8 @@ export function getFramework(detectedFramework?: {
return new SolidStart(detectedFramework.name);
case "qwik":
return new Qwik(detectedFramework.name);
case "vite":
return new Vite(detectedFramework.name);
default:
return new Static(detectedFramework?.name);
}
Expand Down
3 changes: 1 addition & 2 deletions packages/wrangler/src/autoconfig/frameworks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ export type ConfigurationResults = {
export abstract class Framework {
constructor(public name: string = "Static") {}

/** Some frameworks (i.e. Nuxt) don't need additional configuration */
get configured() {
isConfigured(_projectPath: string): boolean {
return false;
}

Expand Down
120 changes: 6 additions & 114 deletions packages/wrangler/src/autoconfig/frameworks/react-router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,123 +8,11 @@ import dedent from "ts-dedent";
import { logger } from "../../logger";
import { transformFile } from "../c3-vendor/codemod";
import { installPackages } from "../c3-vendor/packages";
import { transformViteConfig } from "./utils/vite-config";
import { Framework, getInstalledPackageVersion } from ".";
import type { ConfigurationOptions, ConfigurationResults } from ".";
import type { types } from "recast";

const b = recast.types.builders;
const t = recast.types.namedTypes;

function isPluginsProp(
prop: unknown
): prop is types.namedTypes.ObjectProperty | types.namedTypes.Property {
return (
(t.Property.check(prop) || t.ObjectProperty.check(prop)) &&
t.Identifier.check(prop.key) &&
prop.key.name === "plugins"
);
}

function transformViteConfig(projectPath: string) {
const filePathTS = path.join(projectPath, `vite.config.ts`);
const filePathJS = path.join(projectPath, `vite.config.js`);

let filePath: string;

if (existsSync(filePathTS)) {
filePath = filePathTS;
} else if (existsSync(filePathJS)) {
filePath = filePathJS;
} else {
throw new Error("Could not find Vite config file to modify");
}

transformFile(filePath, {
visitProgram(n) {
// Add an import of the @cloudflare/vite-plugin
// ```
// import {cloudflare} from "@cloudflare/vite-plugin";
// ```
const lastImportIndex = n.node.body.findLastIndex(
(statement) => statement.type === "ImportDeclaration"
);
const lastImport = n.get("body", lastImportIndex);
const importAst = b.importDeclaration(
[b.importSpecifier(b.identifier("cloudflare"))],
b.stringLiteral("@cloudflare/vite-plugin")
);

// Only import if not already imported
if (
!n.node.body.some(
(s) =>
s.type === "ImportDeclaration" &&
s.source.value === "@cloudflare/vite-plugin"
)
) {
lastImport.insertAfter(importAst);
}

return this.traverse(n);
},
visitCallExpression: function (n) {
// Add the imported plugin to the config
// ```
// defineConfig({
// plugins: [cloudflare({ viteEnvironment: { name: 'ssr' } })],
// });
const callee = n.node.callee as types.namedTypes.Identifier;
if (callee.name !== "defineConfig") {
return this.traverse(n);
}

const config = n.node.arguments[0];
assert(t.ObjectExpression.check(config));
const pluginsProp = config.properties.find((prop) => isPluginsProp(prop));
assert(pluginsProp && t.ArrayExpression.check(pluginsProp.value));

// Only add the Cloudflare plugin if it's not already present
if (
!pluginsProp.value.elements.some(
(el) =>
el?.type === "CallExpression" &&
el.callee.type === "Identifier" &&
el.callee.name === "cloudflare"
)
) {
pluginsProp.value.elements.unshift(
b.callExpression(b.identifier("cloudflare"), [
b.objectExpression([
b.objectProperty(
b.identifier("viteEnvironment"),
b.objectExpression([
b.objectProperty(
b.identifier("name"),
b.stringLiteral("ssr")
),
])
),
]),
])
);
}

// Remove netlify plugins, as they conflict
// netlifyReactRouter(), netlify()
pluginsProp.value.elements = pluginsProp.value.elements.filter((el) => {
if (
el?.type === "CallExpression" &&
el.callee.type === "Identifier" &&
["netlifyReactRouter", "netlify"].includes(el.callee.name)
) {
return false;
}
return true;
});
return false;
},
});
}

function transformReactRouterConfig(
projectPath: string,
Expand Down Expand Up @@ -358,7 +246,11 @@ export class ReactRouter extends Framework {
);
}

transformViteConfig(projectPath);
transformViteConfig(projectPath, {
viteEnvironmentName: "ssr",
incompatibleVitePlugins: ["netlifyReactRouter"],
});

transformReactRouterConfig(projectPath, viteEnvironmentKey);
}

Expand Down
Loading
Loading