Skip to content

Commit d9f6a6d

Browse files
Install Vite plugin to vite projects in autoconfig
1 parent 1b3e10d commit d9f6a6d

File tree

6 files changed

+169
-121
lines changed

6 files changed

+169
-121
lines changed

.changeset/petite-swans-train.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"wrangler": minor
3+
---
4+
5+
Install Vite plugin to vite projects in autoconfig

packages/wrangler/src/autoconfig/frameworks/get-framework.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { SolidStart } from "./solid-start";
44
import { Static } from "./static";
55
import { SvelteKit } from "./sveltekit";
66
import { TanstackStart } from "./tanstack";
7+
import { Vite } from "./vite";
78
import type { Framework } from ".";
89

910
export function getFramework(detectedFramework?: {
@@ -21,6 +22,8 @@ export function getFramework(detectedFramework?: {
2122
return new Angular(detectedFramework.name);
2223
case "solid-start":
2324
return new SolidStart(detectedFramework.name);
25+
case "vite":
26+
return new Vite(detectedFramework.name);
2427
default:
2528
return new Static(detectedFramework?.name);
2629
}

packages/wrangler/src/autoconfig/frameworks/tanstack.ts

Lines changed: 2 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1,127 +1,8 @@
1-
import assert from "node:assert";
2-
import { existsSync } from "node:fs";
3-
import path from "node:path";
41
import { brandColor, dim } from "@cloudflare/cli/colors";
5-
import * as recast from "recast";
6-
import { transformFile } from "../c3-vendor/codemod";
72
import { installPackages } from "../c3-vendor/packages";
3+
import { transformViteConfig } from "./utils";
84
import { Framework } from ".";
95
import type { ConfigurationOptions, ConfigurationResults } from ".";
10-
import type { types } from "recast";
11-
12-
const b = recast.types.builders;
13-
const t = recast.types.namedTypes;
14-
15-
function isPluginsProp(
16-
prop: unknown
17-
): prop is types.namedTypes.ObjectProperty | types.namedTypes.Property {
18-
return (
19-
(t.Property.check(prop) || t.ObjectProperty.check(prop)) &&
20-
t.Identifier.check(prop.key) &&
21-
prop.key.name === "plugins"
22-
);
23-
}
24-
25-
function transformViteConfig(projectPath: string) {
26-
const filePathTS = path.join(projectPath, `vite.config.ts`);
27-
const filePathJS = path.join(projectPath, `vite.config.ts`);
28-
29-
let filePath: string;
30-
31-
if (existsSync(filePathTS)) {
32-
filePath = filePathTS;
33-
} else if (existsSync(filePathJS)) {
34-
filePath = filePathJS;
35-
} else {
36-
throw new Error("Could not find Vite config file to modify");
37-
}
38-
39-
transformFile(filePath, {
40-
visitProgram(n) {
41-
// Add an import of the @cloudflare/vite-plugin
42-
// ```
43-
// import {cloudflare} from "@cloudflare/vite-plugin";
44-
// ```
45-
const lastImportIndex = n.node.body.findLastIndex(
46-
(statement) => statement.type === "ImportDeclaration"
47-
);
48-
const lastImport = n.get("body", lastImportIndex);
49-
const importAst = b.importDeclaration(
50-
[b.importSpecifier(b.identifier("cloudflare"))],
51-
b.stringLiteral("@cloudflare/vite-plugin")
52-
);
53-
54-
// Only import if not already imported
55-
if (
56-
!n.node.body.some(
57-
(s) =>
58-
s.type === "ImportDeclaration" &&
59-
s.source.value === "@cloudflare/vite-plugin"
60-
)
61-
) {
62-
lastImport.insertAfter(importAst);
63-
}
64-
65-
return this.traverse(n);
66-
},
67-
visitCallExpression: function (n) {
68-
// Add the imported plugin to the config
69-
// ```
70-
// defineConfig({
71-
// plugins: [cloudflare({ viteEnvironment: { name: 'ssr' } })],
72-
// });
73-
const callee = n.node.callee as types.namedTypes.Identifier;
74-
if (callee.name !== "defineConfig") {
75-
return this.traverse(n);
76-
}
77-
78-
const config = n.node.arguments[0];
79-
assert(t.ObjectExpression.check(config));
80-
const pluginsProp = config.properties.find((prop) => isPluginsProp(prop));
81-
assert(pluginsProp && t.ArrayExpression.check(pluginsProp.value));
82-
83-
// Only add the Cloudflare plugin if it's not already present
84-
if (
85-
!pluginsProp.value.elements.some(
86-
(el) =>
87-
el?.type === "CallExpression" &&
88-
el.callee.type === "Identifier" &&
89-
el.callee.name === "cloudflare"
90-
)
91-
) {
92-
pluginsProp.value.elements.push(
93-
b.callExpression(b.identifier("cloudflare"), [
94-
b.objectExpression([
95-
b.objectProperty(
96-
b.identifier("viteEnvironment"),
97-
b.objectExpression([
98-
b.objectProperty(
99-
b.identifier("name"),
100-
b.stringLiteral("ssr")
101-
),
102-
])
103-
),
104-
]),
105-
])
106-
);
107-
}
108-
109-
// Remove nitro or netlify plugins, as they conflict
110-
// nitro(), nitroV2Plugin(), netlify()
111-
pluginsProp.value.elements = pluginsProp.value.elements.filter((el) => {
112-
if (
113-
el?.type === "CallExpression" &&
114-
el.callee.type === "Identifier" &&
115-
["nitro", "nitroV2Plugin", "netlify"].includes(el.callee.name)
116-
) {
117-
return false;
118-
}
119-
return true;
120-
});
121-
return false;
122-
},
123-
});
124-
}
1256

1267
export class TanstackStart extends Framework {
1278
async configure({
@@ -135,7 +16,7 @@ export class TanstackStart extends Framework {
13516
doneText: `${brandColor(`installed`)} ${dim("@cloudflare/vite-plugin")}`,
13617
});
13718

138-
transformViteConfig(projectPath);
19+
transformViteConfig(projectPath, { viteEnvironmentName: "ssr" });
13920
}
14021

14122
return {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./vite-config";
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import assert from "node:assert";
2+
import { existsSync } from "node:fs";
3+
import path from "node:path";
4+
import * as recast from "recast";
5+
import { transformFile } from "../../c3-vendor/codemod";
6+
import type { types } from "recast";
7+
8+
const b = recast.types.builders;
9+
const t = recast.types.namedTypes;
10+
11+
export function transformViteConfig(
12+
projectPath: string,
13+
options: { viteEnvironmentName?: string } = {}
14+
) {
15+
const filePathTS = path.join(projectPath, `vite.config.ts`);
16+
const filePathJS = path.join(projectPath, `vite.config.ts`);
17+
18+
let filePath: string;
19+
20+
if (existsSync(filePathTS)) {
21+
filePath = filePathTS;
22+
} else if (existsSync(filePathJS)) {
23+
filePath = filePathJS;
24+
} else {
25+
throw new Error("Could not find Vite config file to modify");
26+
}
27+
28+
transformFile(filePath, {
29+
visitProgram(n) {
30+
// Add an import of the @cloudflare/vite-plugin
31+
// ```
32+
// import {cloudflare} from "@cloudflare/vite-plugin";
33+
// ```
34+
const lastImportIndex = n.node.body.findLastIndex(
35+
(statement) => statement.type === "ImportDeclaration"
36+
);
37+
const lastImport = n.get("body", lastImportIndex);
38+
const importAst = b.importDeclaration(
39+
[b.importSpecifier(b.identifier("cloudflare"))],
40+
b.stringLiteral("@cloudflare/vite-plugin")
41+
);
42+
43+
// Only import if not already imported
44+
if (
45+
!n.node.body.some(
46+
(s) =>
47+
s.type === "ImportDeclaration" &&
48+
s.source.value === "@cloudflare/vite-plugin"
49+
)
50+
) {
51+
lastImport.insertAfter(importAst);
52+
}
53+
54+
return this.traverse(n);
55+
},
56+
visitCallExpression: function (n) {
57+
// Add the imported plugin to the config
58+
// ```
59+
// defineConfig({
60+
// plugins: [cloudflare({ viteEnvironment: { name: 'ssr' } })],
61+
// });
62+
const callee = n.node.callee as types.namedTypes.Identifier;
63+
if (callee.name !== "defineConfig") {
64+
return this.traverse(n);
65+
}
66+
67+
const config = n.node.arguments[0];
68+
assert(t.ObjectExpression.check(config));
69+
const pluginsProp = config.properties.find((prop) => isPluginsProp(prop));
70+
assert(pluginsProp && t.ArrayExpression.check(pluginsProp.value));
71+
72+
// Only add the Cloudflare plugin if it's not already present
73+
if (
74+
!pluginsProp.value.elements.some(
75+
(el) =>
76+
el?.type === "CallExpression" &&
77+
el.callee.type === "Identifier" &&
78+
el.callee.name === "cloudflare"
79+
)
80+
) {
81+
pluginsProp.value.elements.push(
82+
b.callExpression(b.identifier("cloudflare"), [
83+
...(options.viteEnvironmentName
84+
? [
85+
b.objectExpression([
86+
b.objectProperty(
87+
b.identifier("viteEnvironment"),
88+
b.objectExpression([
89+
b.objectProperty(
90+
b.identifier("name"),
91+
b.stringLiteral(options.viteEnvironmentName)
92+
),
93+
])
94+
),
95+
]),
96+
]
97+
: []),
98+
])
99+
);
100+
}
101+
102+
// Remove nitro or netlify plugins, as they conflict
103+
// nitro(), nitroV2Plugin(), netlify()
104+
pluginsProp.value.elements = pluginsProp.value.elements.filter((el) => {
105+
if (
106+
el?.type === "CallExpression" &&
107+
el.callee.type === "Identifier" &&
108+
["nitro", "nitroV2Plugin", "netlify"].includes(el.callee.name)
109+
) {
110+
return false;
111+
}
112+
return true;
113+
});
114+
return false;
115+
},
116+
});
117+
}
118+
119+
function isPluginsProp(
120+
prop: unknown
121+
): prop is types.namedTypes.ObjectProperty | types.namedTypes.Property {
122+
return (
123+
(t.Property.check(prop) || t.ObjectProperty.check(prop)) &&
124+
t.Identifier.check(prop.key) &&
125+
prop.key.name === "plugins"
126+
);
127+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { brandColor, dim } from "@cloudflare/cli/colors";
2+
import { installPackages } from "../c3-vendor/packages";
3+
import { transformViteConfig } from "./utils";
4+
import { Framework } from ".";
5+
import type { ConfigurationOptions, ConfigurationResults } from ".";
6+
7+
export class Vite extends Framework {
8+
async configure({
9+
dryRun,
10+
outputDir,
11+
projectPath,
12+
}: ConfigurationOptions): Promise<ConfigurationResults> {
13+
if (!dryRun) {
14+
await installPackages(["@cloudflare/vite-plugin"], {
15+
dev: true,
16+
startText: "Installing the Cloudflare Vite plugin",
17+
doneText: `${brandColor(`installed`)} ${dim("@cloudflare/vite-plugin")}`,
18+
});
19+
20+
transformViteConfig(projectPath);
21+
}
22+
23+
return {
24+
wranglerConfig: {
25+
assets: {
26+
directory: outputDir,
27+
},
28+
},
29+
};
30+
}
31+
}

0 commit comments

Comments
 (0)