Skip to content

Commit 5875adb

Browse files
authored
add vite + worker to vue experimental template (#8358)
* add worker to vue template * add flags * changeset * fix js template * Update tangy-parts-dig.md * fix tests * pr feedback * fix test
1 parent 8461f9b commit 5875adb

File tree

16 files changed

+487
-15
lines changed

16 files changed

+487
-15
lines changed

.changeset/tangy-parts-dig.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"create-cloudflare": patch
3+
---
4+
5+
feat: add Worker + Vite plugin to Vue experimental template

packages/create-cloudflare/e2e-tests/frameworks/framework-test-config-experimental.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,17 +203,18 @@ export default function getFrameworkTestConfigExperimental() {
203203
},
204204
},
205205
vue: {
206+
argv: ["--ts"],
206207
testCommitMessage: true,
207208
unsupportedOSs: ["win32"],
208209
verifyDeploy: {
209210
route: "/",
210211
expectedText: "Vite App",
211212
},
212213
verifyPreview: {
214+
previewArgs: ["--host=127.0.0.1"],
213215
route: "/",
214216
expectedText: "Vite App",
215217
},
216-
flags: ["--ts"],
217218
},
218219
};
219220
}

packages/create-cloudflare/templates-experimental/vue/c3.ts

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,94 @@
1+
import { logRaw } from "@cloudflare/cli";
2+
import { brandColor, dim } from "@cloudflare/cli/colors";
3+
import { inputPrompt, spinner } from "@cloudflare/cli/interactive";
14
import { runFrameworkGenerator } from "frameworks/index";
5+
import { readJSON, usesTypescript, writeJSON } from "helpers/files";
26
import { detectPackageManager } from "helpers/packageManagers";
7+
import { installPackages } from "helpers/packages";
38
import type { TemplateConfig } from "../../src/templates";
49
import type { C3Context } from "types";
510

611
const { npm } = detectPackageManager();
712

813
const generate = async (ctx: C3Context) => {
9-
await runFrameworkGenerator(ctx, [ctx.project.name]);
14+
const lang =
15+
ctx.args.lang ??
16+
(await inputPrompt({
17+
type: "select",
18+
question: "Would you like to use TypeScript?",
19+
label: "Language",
20+
options: [
21+
{ label: "TypeScript", value: "ts" },
22+
{ label: "JavaScript", value: "js" },
23+
],
24+
}));
25+
await runFrameworkGenerator(ctx, [
26+
ctx.project.name,
27+
"--router",
28+
lang === "ts" ? "--ts" : "",
29+
]);
30+
logRaw("");
1031
};
1132

33+
const configure = async (ctx: C3Context) => {
34+
await installPackages(["@cloudflare/vite-plugin"], {
35+
dev: true,
36+
startText: "Installing the Cloudflare Vite plugin",
37+
doneText: `${brandColor(`installed`)} ${dim("@cloudflare/vite-plugin")}`,
38+
});
39+
40+
if (usesTypescript(ctx)) {
41+
updateTsconfigJson();
42+
}
43+
};
44+
45+
function updateTsconfigJson() {
46+
const s = spinner();
47+
s.start(`Updating tsconfig.json config`);
48+
// Add a reference to the extra tsconfig.worker.json file.
49+
// ```
50+
// "references": [ ..., { path: "./tsconfig.worker.json" } ]
51+
// ```
52+
const tsconfig = readJSON("tsconfig.json") as { references: object[] };
53+
if (tsconfig && typeof tsconfig === "object") {
54+
tsconfig.references ??= [];
55+
tsconfig.references.push({ path: "./tsconfig.worker.json" });
56+
}
57+
writeJSON("tsconfig.json", tsconfig);
58+
s.stop(`${brandColor(`updated`)} ${dim(`\`tsconfig.json\``)}`);
59+
}
60+
1261
const config: TemplateConfig = {
1362
configVersion: 1,
1463
id: "vue",
1564
frameworkCli: "create-vue",
1665
platform: "workers",
1766
displayName: "Vue",
67+
path: "templates-experimental/vue",
1868
copyFiles: {
19-
path: "./templates",
69+
async selectVariant(ctx) {
70+
// Note: this `selectVariant` function should not be needed
71+
// this is just a quick workaround until
72+
// https://github.com/cloudflare/workers-sdk/issues/7495
73+
// is resolved
74+
return usesTypescript(ctx) ? "ts" : "js";
75+
},
76+
variants: {
77+
ts: {
78+
path: "./ts",
79+
},
80+
js: {
81+
path: "./js",
82+
},
83+
},
2084
},
21-
path: "templates-experimental/vue",
85+
configure,
2286
generate,
23-
transformPackageJson: async () => ({
87+
transformPackageJson: async (_, ctx) => ({
2488
scripts: {
2589
deploy: `${npm} run build && wrangler deploy`,
2690
preview: `${npm} run build && wrangler dev`,
91+
...(usesTypescript(ctx) && { "cf-typegen": `wrangler types` }),
2792
},
2893
}),
2994
devScript: "dev",
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export default {
2+
fetch(request, env) {
3+
const url = new URL(request.url);
4+
5+
if (url.pathname.startsWith("/api/")) {
6+
return Response.json({
7+
name: "Cloudflare",
8+
});
9+
}
10+
11+
return env.ASSETS.fetch(request);
12+
},
13+
};
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<script setup>
2+
import { RouterLink, RouterView } from 'vue-router'
3+
import HelloWorld from './components/HelloWorld.vue'
4+
import { ref } from 'vue'
5+
6+
const name = ref('Unknown')
7+
8+
const getName = async () => {
9+
const res = await fetch('/api/')
10+
const data = await res.json()
11+
name.value = data.name
12+
}
13+
</script>
14+
15+
<template>
16+
<header>
17+
<img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="125" height="125" />
18+
19+
<div class="wrapper">
20+
<HelloWorld msg="You did it!" />
21+
<button class="green" @click="getName" aria-label="get name">
22+
Name from API is: {{ name }}
23+
</button>
24+
<p>Edit <code>server/index.js</code> to change what the API gets</p>
25+
<nav>
26+
<RouterLink to="/">Home</RouterLink>
27+
<RouterLink to="/about">About</RouterLink>
28+
</nav>
29+
</div>
30+
</header>
31+
32+
<RouterView />
33+
</template>
34+
35+
<style scoped>
36+
header {
37+
line-height: 1.5;
38+
max-height: 100vh;
39+
}
40+
41+
.logo {
42+
display: block;
43+
margin: 0 auto 2rem;
44+
}
45+
46+
nav {
47+
width: 100%;
48+
font-size: 12px;
49+
text-align: center;
50+
margin-top: 2rem;
51+
}
52+
53+
nav a.router-link-exact-active {
54+
color: var(--color-text);
55+
}
56+
57+
nav a.router-link-exact-active:hover {
58+
background-color: transparent;
59+
}
60+
61+
nav a {
62+
display: inline-block;
63+
padding: 0 1rem;
64+
border-left: 1px solid var(--color-border);
65+
}
66+
67+
nav a:first-of-type {
68+
border: 0;
69+
}
70+
71+
button {
72+
background-color: hsla(160, 100%, 37%, 1);
73+
color: var(--color-background);
74+
border: 0;
75+
padding: 0.5rem 1rem;
76+
border-radius: 0.25rem;
77+
cursor: pointer;
78+
margin: 1rem 0 0.5rem 0;
79+
}
80+
81+
@media (min-width: 1024px) {
82+
header {
83+
display: flex;
84+
place-items: center;
85+
padding-right: calc(var(--section-gap) / 2);
86+
}
87+
88+
.logo {
89+
margin: 0 2rem 0 0;
90+
}
91+
92+
header .wrapper {
93+
display: flex;
94+
place-items: flex-start;
95+
flex-wrap: wrap;
96+
}
97+
98+
nav {
99+
text-align: left;
100+
margin-left: -1rem;
101+
font-size: 1rem;
102+
103+
padding: 1rem 0;
104+
margin-top: 1rem;
105+
}
106+
}
107+
</style>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<script setup>
2+
defineProps({
3+
msg: {
4+
type: String,
5+
required: true,
6+
},
7+
})
8+
</script>
9+
10+
<template>
11+
<div class="greetings">
12+
<h1 class="green">{{ msg }}</h1>
13+
<h3>
14+
You’ve successfully created a project with
15+
<a href="https://vite.dev/" target="_blank" rel="noopener">Vite</a> +
16+
<a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a> +
17+
<a href="https://developers.cloudflare.com/workers/" target="_blank" rel="noopener"
18+
>Cloudflare Workers</a
19+
>. What's next?
20+
</h3>
21+
</div>
22+
</template>
23+
24+
<style scoped>
25+
h1 {
26+
font-weight: 500;
27+
font-size: 2.6rem;
28+
position: relative;
29+
top: -10px;
30+
}
31+
32+
h3 {
33+
font-size: 1.2rem;
34+
}
35+
36+
.greetings h1,
37+
.greetings h3 {
38+
text-align: center;
39+
}
40+
41+
@media (min-width: 1024px) {
42+
.greetings h1,
43+
.greetings h3 {
44+
text-align: left;
45+
}
46+
}
47+
</style>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { fileURLToPath, URL } from 'node:url'
2+
3+
import { defineConfig } from 'vite'
4+
import vue from '@vitejs/plugin-vue'
5+
import vueDevTools from 'vite-plugin-vue-devtools'
6+
7+
import { cloudflare } from "@cloudflare/vite-plugin"
8+
9+
// https://vite.dev/config/
10+
export default defineConfig({
11+
plugins: [
12+
vue(),
13+
vueDevTools(),
14+
cloudflare()
15+
],
16+
resolve: {
17+
alias: {
18+
'@': fileURLToPath(new URL('./src', import.meta.url))
19+
},
20+
},
21+
})
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "<TBD>",
3+
"compatibility_date": "<TBD>",
4+
"main": "server/index.ts",
5+
"assets": {
6+
"not_found_handling": "single-page-application",
7+
"binding": "ASSETS"
8+
},
9+
"observability": {
10+
"enabled": true
11+
}
12+
}

packages/create-cloudflare/templates-experimental/vue/templates/wrangler.jsonc

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export default {
2+
fetch(request, env) {
3+
const url = new URL(request.url);
4+
5+
if (url.pathname.startsWith("/api/")) {
6+
return Response.json({
7+
name: "Cloudflare",
8+
});
9+
}
10+
11+
return env.ASSETS.fetch(request);
12+
},
13+
} satisfies ExportedHandler<Env>;

0 commit comments

Comments
 (0)