Skip to content

Commit

Permalink
C3: Nuxt template dev improvements (#4996)
Browse files Browse the repository at this point in the history
* C3: Update dev bindings support in nuxt template

* Add initial wrangler.toml for pages frameworks with getBindingsProxy

* Changeset

* Use hello-world wrangler.toml template for qwik and nuxt

* Increase wait time in framework e2e to combat verifyDevScript flakiness

* Fixup changesets

* Wait for dev server a little longer. And fix changeset

* Attempt to resolve verifyDev flakiness

* Skip nuxt e2e on win32
  • Loading branch information
jculvey committed Feb 13, 2024
1 parent 96b18a7 commit 246512c
Show file tree
Hide file tree
Showing 11 changed files with 202 additions and 21 deletions.
7 changes: 7 additions & 0 deletions .changeset/slimy-apples-reply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"create-cloudflare": minor
---

feature: Add `getBindingsProxy` support to `nuxt` template via `nitro-cloudflare-dev` module.

The `nuxt` template now uses the default dev command from `create-nuxt` instead of using `wrangler paves dev` on build output in order to improve the developer workflow. `nitro-cloudflare-dev` is a nitro module that leverages `getBindingsProxy` and allows bindings to work in nitro commands.
5 changes: 5 additions & 0 deletions .changeset/spotty-suns-learn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"create-cloudflare": patch
---

feature: Add an empty `wrangler.toml` file to qwik and nuxt templates.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default eventHandler(async (event) => {
if (!event.context.cloudflare) {
return { success: false };
}
const { TEST } = event.context.cloudflare.env;

return { value: TEST, success: true };
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[vars]
TEST = "C3_TEST"
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ export const onGet: RequestHandler = async ({ platform, json }) => {
return;
}

json(200, { value: platform.env["TEST"], version: 1 });
json(200, { value: platform.env["TEST"], success: true });
};
17 changes: 14 additions & 3 deletions packages/create-cloudflare/e2e-tests/frameworks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,21 @@ const frameworkTests: Record<string, FrameworkTestConfig> = {
nuxt: {
testCommitMessage: true,
timeout: LONG_TIMEOUT,
unsupportedOSs: ["win32"],
verifyDeploy: {
route: "/",
expectedText: "Welcome to Nuxt!",
},
verifyDev: {
route: "/test",
expectedText: "C3_TEST",
},
verifyBuild: {
outputDir: "./dist",
script: "build",
route: "/test",
expectedText: "C3_TEST",
},
},
react: {
testCommitMessage: true,
Expand Down Expand Up @@ -421,8 +432,8 @@ const verifyDevScript = async (
logStream
);

// Wait a few seconds for dev server to spin up
await sleep(4000);
// Wait an eternity for the dev server to spin up
await sleep(12000);

// Make a request to the specified test route
const res = await fetch(`http://localhost:${TEST_PORT}${verifyDev.route}`);
Expand Down Expand Up @@ -474,7 +485,7 @@ const verifyBuildScript = async (
);

// Wait a few seconds for dev server to spin up
await sleep(4000);
await sleep(7000);

// Make a request to the specified test route
const res = await fetch(`http://localhost:${TEST_PORT}${route}`);
Expand Down
7 changes: 6 additions & 1 deletion packages/create-cloudflare/src/workers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ import type { C3Context } from "types";

const { npm } = detectPackageManager();

export const wranglerTomlExists = (ctx: C3Context) => {
const wranglerTomlPath = resolve(ctx.project.path, "wrangler.toml");
return existsSync(wranglerTomlPath);
};

export const readWranglerToml = (ctx: C3Context) => {
const wranglerTomlPath = resolve(ctx.project.path, "wrangler.toml");
return readFile(wranglerTomlPath);
Expand All @@ -26,7 +31,7 @@ export const writeWranglerToml = (ctx: C3Context, contents: string) => {
* to the selected project name and adding the latest compatibility date.
*/
export const updateWranglerToml = async (ctx: C3Context) => {
if (ctx.template.platform !== "workers") {
if (!wranglerTomlExists(ctx)) {
return;
}

Expand Down
72 changes: 56 additions & 16 deletions packages/create-cloudflare/templates/nuxt/c3.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { logRaw } from "@cloudflare/cli";
import { brandColor, dim } from "@cloudflare/cli/colors";
import { spinner } from "@cloudflare/cli/interactive";
import { runFrameworkGenerator } from "helpers/command";
import { compatDateFlag, writeFile } from "helpers/files";
import { transformFile } from "helpers/codemod";
import { installPackages, runFrameworkGenerator } from "helpers/command";
import { writeFile } from "helpers/files";
import { detectPackageManager } from "helpers/packages";
import * as recast from "recast";
import type { TemplateConfig } from "../../src/templates";
import type { C3Context } from "types";

Expand All @@ -28,31 +28,71 @@ const generate = async (ctx: C3Context) => {
};

const configure = async () => {
const configFileName = "nuxt.config.ts";
const configFilePath = resolve(configFileName);
await installPackages(["nitro-cloudflare-dev"], {
dev: true,
startText: "Installing nitro module `nitro-cloudflare-dev`",
doneText: `${brandColor("installed")} ${dim(`via \`${npm} install\``)}`,
});
updateNuxtConfig();
};

const updateNuxtConfig = () => {
const s = spinner();
s.start(`Updating \`${configFileName}\``);
// Add the cloudflare preset into the configuration file.
const originalConfigFile = readFileSync(configFilePath, "utf8");
const updatedConfigFile = originalConfigFile.replace(
"defineNuxtConfig({",
"defineNuxtConfig({\n nitro: {\n preset: 'cloudflare-pages'\n },"

const configFile = "nuxt.config.ts";
s.start(`Updating \`${configFile}\``);

const b = recast.types.builders;

const presetDef = b.objectProperty(
b.identifier("nitro"),
b.objectExpression([
b.objectProperty(
b.identifier("preset"),
b.stringLiteral("cloudflare-pages")
),
])
);

const moduleDef = b.objectProperty(
b.identifier("modules"),
b.arrayExpression([b.stringLiteral("nitro-cloudflare-dev")])
);
writeFile(configFilePath, updatedConfigFile);
s.stop(`${brandColor(`updated`)} ${dim(`\`${configFileName}\``)}`);

transformFile(configFile, {
visitCallExpression: function (n) {
const callee = n.node.callee as recast.types.namedTypes.Identifier;
if (callee.name === "defineNuxtConfig") {
const obj = n.node
.arguments[0] as recast.types.namedTypes.ObjectExpression;

obj.properties.push(presetDef);
obj.properties.push(moduleDef);
}

return this.traverse(n);
},
});

s.stop(`${brandColor(`updated`)} ${dim(`\`${configFile}\``)}`);
};

const config: TemplateConfig = {
configVersion: 1,
id: "nuxt",
platform: "pages",
copyFiles: {
path: "./templates",
},
displayName: "Nuxt",
devScript: "dev",
deployScript: "deploy",
generate,
configure,
transformPackageJson: async () => ({
scripts: {
"pages:dev": `wrangler pages dev ${await compatDateFlag()} --proxy 3000 -- ${npm} run dev`,
"pages:deploy": `${npm} run build && wrangler pages deploy ./dist`,
deploy: `${npm} run build && wrangler pages deploy ./dist`,
preview: `${npm} run build && wrangler pages dev ./dist`,
},
}),
};
Expand Down
50 changes: 50 additions & 0 deletions packages/create-cloudflare/templates/nuxt/templates/wrangler.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name = "<TBD>"
compatibility_date = "<TBD>"

# Variable bindings. These are arbitrary, plaintext strings (similar to environment variables)
# Note: Use secrets to store sensitive data.
# Docs: https://developers.cloudflare.com/workers/platform/environment-variables
# [vars]
# MY_VARIABLE = "production_value"

# Bind a KV Namespace. Use KV as persistent storage for small key-value pairs.
# Docs: https://developers.cloudflare.com/workers/runtime-apis/kv
# [[kv_namespaces]]
# binding = "MY_KV_NAMESPACE"
# id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

# Bind an R2 Bucket. Use R2 to store arbitrarily large blobs of data, such as files.
# Docs: https://developers.cloudflare.com/r2/api/workers/workers-api-usage/
# [[r2_buckets]]
# binding = "MY_BUCKET"
# bucket_name = "my-bucket"

# Bind a Queue producer. Use this binding to schedule an arbitrary task that may be processed later by a Queue consumer.
# Docs: https://developers.cloudflare.com/queues/get-started
# [[queues.producers]]
# binding = "MY_QUEUE"
# queue = "my-queue"

# Bind a Queue consumer. Queue Consumers can retrieve tasks scheduled by Producers to act on them.
# Docs: https://developers.cloudflare.com/queues/get-started
# [[queues.consumers]]
# queue = "my-queue"

# Bind another Worker service. Use this binding to call another Worker without network overhead.
# Docs: https://developers.cloudflare.com/workers/platform/services
# [[services]]
# binding = "MY_SERVICE"
# service = "my-service"

# Bind a Durable Object. Durable objects are a scale-to-zero compute primitive based on the actor model.
# Durable Objects can live for as long as needed. Use these when you need a long-running "server", such as in realtime apps.
# Docs: https://developers.cloudflare.com/workers/runtime-apis/durable-objects
# [[durable_objects.bindings]]
# name = "MY_DURABLE_OBJECT"
# class_name = "MyDurableObject"

# Durable Object migrations.
# Docs: https://developers.cloudflare.com/workers/learning/using-durable-objects#configure-durable-object-classes-with-migrations
# [[migrations]]
# tag = "v1"
# new_classes = ["MyDurableObject"]
3 changes: 3 additions & 0 deletions packages/create-cloudflare/templates/qwik/c3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ const config: TemplateConfig = {
id: "qwik",
displayName: "Qwik",
platform: "pages",
copyFiles: {
path: "./templates",
},
devScript: "dev",
deployScript: "deploy",
generate,
Expand Down
50 changes: 50 additions & 0 deletions packages/create-cloudflare/templates/qwik/templates/wrangler.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name = "<TBD>"
compatibility_date = "<TBD>"

# Variable bindings. These are arbitrary, plaintext strings (similar to environment variables)
# Note: Use secrets to store sensitive data.
# Docs: https://developers.cloudflare.com/workers/platform/environment-variables
# [vars]
# MY_VARIABLE = "production_value"

# Bind a KV Namespace. Use KV as persistent storage for small key-value pairs.
# Docs: https://developers.cloudflare.com/workers/runtime-apis/kv
# [[kv_namespaces]]
# binding = "MY_KV_NAMESPACE"
# id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

# Bind an R2 Bucket. Use R2 to store arbitrarily large blobs of data, such as files.
# Docs: https://developers.cloudflare.com/r2/api/workers/workers-api-usage/
# [[r2_buckets]]
# binding = "MY_BUCKET"
# bucket_name = "my-bucket"

# Bind a Queue producer. Use this binding to schedule an arbitrary task that may be processed later by a Queue consumer.
# Docs: https://developers.cloudflare.com/queues/get-started
# [[queues.producers]]
# binding = "MY_QUEUE"
# queue = "my-queue"

# Bind a Queue consumer. Queue Consumers can retrieve tasks scheduled by Producers to act on them.
# Docs: https://developers.cloudflare.com/queues/get-started
# [[queues.consumers]]
# queue = "my-queue"

# Bind another Worker service. Use this binding to call another Worker without network overhead.
# Docs: https://developers.cloudflare.com/workers/platform/services
# [[services]]
# binding = "MY_SERVICE"
# service = "my-service"

# Bind a Durable Object. Durable objects are a scale-to-zero compute primitive based on the actor model.
# Durable Objects can live for as long as needed. Use these when you need a long-running "server", such as in realtime apps.
# Docs: https://developers.cloudflare.com/workers/runtime-apis/durable-objects
# [[durable_objects.bindings]]
# name = "MY_DURABLE_OBJECT"
# class_name = "MyDurableObject"

# Durable Object migrations.
# Docs: https://developers.cloudflare.com/workers/learning/using-durable-objects#configure-durable-object-classes-with-migrations
# [[migrations]]
# tag = "v1"
# new_classes = ["MyDurableObject"]

0 comments on commit 246512c

Please sign in to comment.