Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C3: Nuxt template dev improvements #4996

Merged
merged 9 commits into from
Feb 13, 2024
7 changes: 7 additions & 0 deletions .changeset/slimy-apples-reply.md
dario-piotrowicz marked this conversation as resolved.
Show resolved Hide resolved
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
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
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"]
Loading