diff --git a/.changeset/young-doors-think.md b/.changeset/young-doors-think.md new file mode 100644 index 000000000000..ec3bb130a485 --- /dev/null +++ b/.changeset/young-doors-think.md @@ -0,0 +1,5 @@ +--- +"wrangler": minor +--- + +feat: implements the `--experimental-dev-env` (shorthand: `--x-dev-env`) flag for `wrangler pages dev` diff --git a/packages/wrangler/e2e/__snapshots__/pages-dev.test.ts.snap b/packages/wrangler/e2e/__snapshots__/pages-dev.test.ts.snap new file mode 100644 index 000000000000..0d5afdc7a27d --- /dev/null +++ b/packages/wrangler/e2e/__snapshots__/pages-dev.test.ts.snap @@ -0,0 +1,80 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Pages 'wrangler pages dev --x-dev-env' > should merge (with override) \`wrangler.toml\` configuration with configuration provided via the command line, with command line args taking precedence 1`] = ` +"✨ Compiled Worker successfully +▲ [WARNING] WARNING: You have Durable Object bindings that are not defined locally in the worker being developed. + Be aware that changes to the data stored in these Durable Objects will be permanent and affect the live instances. + Remote Durable Objects that are affected: + - {"name":"DO_BINDING_1_TOML","class_name":"DO_1_TOML","script_name":"DO_SCRIPT_1_TOML"} + - {"name":"DO_BINDING_2_TOML","class_name":"DO_2_TOML","script_name":"DO_SCRIPT_2_TOML"} +Your worker has access to the following bindings: +- Durable Objects: + - DO_BINDING_1_TOML: NEW_DO_1 (defined in NEW_DO_SCRIPT_1) + - DO_BINDING_2_TOML: DO_2_TOML (defined in DO_SCRIPT_2_TOML) + - DO_BINDING_3_ARGS: DO_3_ARGS (defined in DO_SCRIPT_3_ARGS) +- KV Namespaces: + - KV_BINDING_1_TOML: NEW_KV_ID_1 + - KV_BINDING_2_TOML: KV_ID_2_TOML + - KV_BINDING_3_ARGS: KV_ID_3_ARGS +- D1 Databases: + - D1_BINDING_1_TOML: local-D1_BINDING_1_TOML=NEW_D1_NAME_1 (NEW_D1_NAME_1) + - D1_BINDING_2_TOML: D1_NAME_2_TOML (D1_ID_2_TOML) + - D1_BINDING_3_ARGS: local-D1_BINDING_3_ARGS=D1_NAME_3_ARGS (D1_NAME_3_ARGS) +- R2 Buckets: + - R2_BINDING_1_TOML: NEW_R2_BUCKET_1 + - R2_BINDING_2_TOML: R2_BUCKET_2_TOML + - R2_BINDING_3_TOML: R2_BUCKET_3_ARGS +- Services: + - SERVICE_BINDING_1_TOML: NEW_SERVICE_NAME_1 + - SERVICE_BINDING_2_TOML: SERVICE_NAME_2_TOML + - SERVICE_BINDING_3_TOML: SERVICE_NAME_3_ARGS +- AI: + - Name: AI_BINDING_2_TOML +- Vars: + - VAR1: "(hidden)" + - VAR2: "VAR_2_TOML" + - VAR3: "(hidden)" +▲ [WARNING] This worker is bound to live services: SERVICE_BINDING_1_TOML (NEW_SERVICE_NAME_1), SERVICE_BINDING_3_TOML (SERVICE_NAME_3_ARGS), SERVICE_BINDING_2_TOML (SERVICE_NAME_2_TOML) +▲ [WARNING] Using Workers AI always accesses your Cloudflare account in order to run AI models, and so will incur usage charges even in local development. +" +`; + +exports[`Pages 'wrangler pages dev' > should merge (with override) \`wrangler.toml\` configuration with configuration provided via the command line, with command line args taking precedence 1`] = ` +"✨ Compiled Worker successfully +▲ [WARNING] WARNING: You have Durable Object bindings that are not defined locally in the worker being developed. + Be aware that changes to the data stored in these Durable Objects will be permanent and affect the live instances. + Remote Durable Objects that are affected: + - {"name":"DO_BINDING_1_TOML","class_name":"DO_1_TOML","script_name":"DO_SCRIPT_1_TOML"} + - {"name":"DO_BINDING_2_TOML","class_name":"DO_2_TOML","script_name":"DO_SCRIPT_2_TOML"} +▲ [WARNING] This worker is bound to live services: SERVICE_BINDING_1_TOML (SERVICE_NAME_1_TOML), SERVICE_BINDING_2_TOML (SERVICE_NAME_2_TOML) +Your worker has access to the following bindings: +- Durable Objects: + - DO_BINDING_1_TOML: NEW_DO_1 (defined in NEW_DO_SCRIPT_1) + - DO_BINDING_2_TOML: DO_2_TOML (defined in DO_SCRIPT_2_TOML) + - DO_BINDING_3_ARGS: DO_3_ARGS (defined in DO_SCRIPT_3_ARGS) +- KV Namespaces: + - KV_BINDING_1_TOML: NEW_KV_ID_1 + - KV_BINDING_2_TOML: KV_ID_2_TOML + - KV_BINDING_3_ARGS: KV_ID_3_ARGS +- D1 Databases: + - D1_BINDING_1_TOML: local-D1_BINDING_1_TOML=NEW_D1_NAME_1 (NEW_D1_NAME_1) + - D1_BINDING_2_TOML: D1_NAME_2_TOML (D1_ID_2_TOML) + - D1_BINDING_3_ARGS: local-D1_BINDING_3_ARGS=D1_NAME_3_ARGS (D1_NAME_3_ARGS) +- R2 Buckets: + - R2_BINDING_1_TOML: NEW_R2_BUCKET_1 + - R2_BINDING_2_TOML: R2_BUCKET_2_TOML + - R2_BINDING_3_TOML: R2_BUCKET_3_ARGS +- Services: + - SERVICE_BINDING_1_TOML: NEW_SERVICE_NAME_1 + - SERVICE_BINDING_2_TOML: SERVICE_NAME_2_TOML + - SERVICE_BINDING_3_TOML: SERVICE_NAME_3_ARGS +- AI: + - Name: AI_BINDING_2_TOML +- Vars: + - VAR1: "(hidden)" + - VAR2: "VAR_2_TOML" + - VAR3: "(hidden)" +▲ [WARNING] ⎔ Support for service bindings in local mode is experimental and may change. +▲ [WARNING] ⎔ Support for external Durable Objects in local mode is experimental and may change. +" +`; diff --git a/packages/wrangler/e2e/pages-dev.test.ts b/packages/wrangler/e2e/pages-dev.test.ts index caea65fa4cb9..e4bc859263d5 100644 --- a/packages/wrangler/e2e/pages-dev.test.ts +++ b/packages/wrangler/e2e/pages-dev.test.ts @@ -7,7 +7,10 @@ import { WranglerE2ETestHelper } from "./helpers/e2e-wrangler-test"; import { fetchText } from "./helpers/fetch-text"; import { normalizeOutput } from "./helpers/normalize"; -describe("pages dev", () => { +describe.each([ + { cmd: "wrangler pages dev" }, + { cmd: "wrangler pages dev --x-dev-env" }, +])("Pages $cmd", ({ cmd }) => { it("should warn if no [--compatibility_date] command line arg was specified", async () => { const helper = new WranglerE2ETestHelper(); await helper.seed({ @@ -19,7 +22,7 @@ describe("pages dev", () => { }`, }); const port = await getPort(); - const worker = helper.runLongLived(`wrangler pages dev --port ${port} .`); + const worker = helper.runLongLived(`${cmd} --port ${port} .`); const { url } = await worker.waitForReady(); const currentDate = new Date().toISOString().substring(0, 10); @@ -38,14 +41,14 @@ describe("pages dev", () => { ); const text = await fetchText(url); - expect(text).toMatchInlineSnapshot('"Testing [--compatibility_date]"'); + expect(text).toBe("Testing [--compatibility_date]"); }); it("should warn that [--experimental-local] is no longer required, if specified", async () => { const helper = new WranglerE2ETestHelper(); const port = await getPort(); const worker = helper.runLongLived( - `wrangler pages dev --port ${port} . --experimental-local` + `${cmd} --port ${port} . --experimental-local` ); await helper.seed({ "_worker.js": dedent` @@ -57,7 +60,7 @@ describe("pages dev", () => { }); const { url } = await worker.waitForReady(); const text = await fetchText(url); - expect(text).toMatchInlineSnapshot(`"Testing [--experimental-local]"`); + expect(text).toBe("Testing [--experimental-local]"); expect(await worker.currentOutput).toContain( `--experimental-local is no longer required and will be removed in a future version` ); @@ -67,22 +70,19 @@ describe("pages dev", () => { const helper = new WranglerE2ETestHelper(); const port = await getPort(); const worker = helper.runLongLived( - `wrangler pages dev --port ${port} . --service STAGING_SERVICE=test-worker@staging` + `${cmd} --port ${port} . --service STAGING_SERVICE=test-worker@staging` ); await worker.readUntil( /Support for service binding environments is experimental/ ); - await worker.readUntil( - /Support for service bindings in local mode is experimental and may change/ - ); }); it("should warn if bindings specified as args in the command line are invalid", async () => { const helper = new WranglerE2ETestHelper(); const port = await getPort(); const worker = helper.runLongLived( - `wrangler pages dev . --port ${port} --service test --kv = --do test --d1 = --r2 =` + `${cmd} . --port ${port} --service test --kv = --do test --d1 = --r2 =` ); await worker.waitForReady(); expect(await worker.currentOutput).toContain( @@ -114,7 +114,7 @@ describe("pages dev", () => { }); const port = await getPort(); const worker = helper.runLongLived( - `wrangler pages dev . --port ${port} --service TEST_SERVICE=test-worker --kv TEST_KV --do TEST_DO=TestDurableObject@a --d1 TEST_D1 --r2 TEST_R2` + `${cmd} . --port ${port} --service TEST_SERVICE=test-worker --kv TEST_KV --do TEST_DO=TestDurableObject@a --d1 TEST_D1 --r2 TEST_R2` ); await worker.waitForReady(); expect(normalizeOutput(worker.currentOutput).replace(/\s/g, "")).toContain( @@ -150,16 +150,16 @@ describe("pages dev", () => { `, }); const port = await getPort(); - const worker = helper.runLongLived(`wrangler pages dev --port ${port}`); + const worker = helper.runLongLived(`${cmd} --port ${port}`); const { url } = await worker.waitForReady(); const text = await fetchText(url); - expect(text).toMatchInlineSnapshot('"Pages supports wrangler.toml ⚡️⚡️"'); + expect(text).toBe("Pages supports wrangler.toml ⚡️⚡️"); }); it("should recover from syntax error during dev session (_worker)", async () => { const helper = new WranglerE2ETestHelper(); - const worker = helper.runLongLived("wrangler pages dev ."); + const worker = helper.runLongLived(`${cmd} .`); await helper.seed({ "_worker.js": dedent` @@ -172,9 +172,9 @@ describe("pages dev", () => { const { url } = await worker.waitForReady(); - await expect( - fetch(url).then((r) => r.text()) - ).resolves.toMatchInlineSnapshot('"Hello World!"'); + await expect(fetch(url).then((r) => r.text())).resolves.toBe( + "Hello World!" + ); await helper.seed({ "_worker.js": dedent` @@ -201,15 +201,15 @@ describe("pages dev", () => { }); await worker.waitForReload(); - await expect( - fetch(url).then((r) => r.text()) - ).resolves.toMatchInlineSnapshot('"Updated Worker!"'); + await expect(fetch(url).then((r) => r.text())).resolves.toBe( + "Updated Worker!" + ); }); it("should recover from syntax error during dev session (Functions)", async () => { const helper = new WranglerE2ETestHelper(); const port = await getPort(); - const worker = helper.runLongLived(`wrangler pages dev --port ${port} .`); + const worker = helper.runLongLived(`${cmd} --port ${port} .`); await helper.seed({ "functions/_middleware.js": dedent` @@ -220,9 +220,9 @@ describe("pages dev", () => { const { url } = await worker.waitForReady(); - await expect( - fetch(url).then((r) => r.text()) - ).resolves.toMatchInlineSnapshot('"Hello World!"'); + await expect(fetch(url).then((r) => r.text())).resolves.toBe( + "Hello World!" + ); await helper.seed({ "functions/_middleware.js": dedent` @@ -245,9 +245,9 @@ describe("pages dev", () => { }); await worker.waitForReload(); - await expect( - fetch(url).then((r) => r.text()) - ).resolves.toMatchInlineSnapshot('"Updated Worker!"'); + await expect(fetch(url).then((r) => r.text())).resolves.toBe( + "Updated Worker!" + ); }); it("should validate _routes.json during dev session, and fallback to default value", async () => { @@ -266,13 +266,13 @@ describe("pages dev", () => { `, }); const port = await getPort(); - const worker = helper.runLongLived(`wrangler pages dev --port ${port} .`); + const worker = helper.runLongLived(`${cmd} --port ${port} .`); const { url } = await worker.waitForReady(); const foo = await fetchText(`${url}/foo`); - expect(foo).toMatchInlineSnapshot('"FOO"'); + expect(foo).toBe("FOO"); // invalid _routes.json because include rule does not start with `/` await helper.seed({ @@ -292,7 +292,7 @@ describe("pages dev", () => { it("should use top-level configuration specified in `wrangler.toml`", async () => { const helper = new WranglerE2ETestHelper(); const port = await getPort(); - const worker = helper.runLongLived(`wrangler pages dev --port ${port}`); + const worker = helper.runLongLived(`${cmd} --port ${port}`); await helper.seed({ "public/_worker.js": dedent` export default { @@ -319,9 +319,7 @@ describe("pages dev", () => { const text = await fetchText(url); - expect(text).toMatchInlineSnapshot( - '"⚡️ Pages ⚡️ supports wrangler.toml"' - ); + expect(text).toBe("⚡️ Pages ⚡️ supports wrangler.toml"); expect(normalizeOutput(worker.currentOutput).replace(/\s/g, "")).toContain( ` Your worker has access to the following bindings: @@ -347,7 +345,7 @@ describe("pages dev", () => { ` --ai AI_BINDING_2_TOML`, ` --port ${port}`, ]; - const worker = helper.runLongLived(`wrangler pages dev ${flags.join("")}`); + const worker = helper.runLongLived(`${cmd} ${flags.join("")}`); await helper.seed({ "public/_worker.js": dedent` export default { @@ -430,45 +428,7 @@ describe("pages dev", () => { "⎔ Starting local server..." ); - expect(prestartOutput).toMatchInlineSnapshot(` - "✨ Compiled Worker successfully - ▲ [WARNING] WARNING: You have Durable Object bindings that are not defined locally in the worker being developed. - Be aware that changes to the data stored in these Durable Objects will be permanent and affect the live instances. - Remote Durable Objects that are affected: - - {"name":"DO_BINDING_1_TOML","class_name":"DO_1_TOML","script_name":"DO_SCRIPT_1_TOML"} - - {"name":"DO_BINDING_2_TOML","class_name":"DO_2_TOML","script_name":"DO_SCRIPT_2_TOML"} - ▲ [WARNING] This worker is bound to live services: SERVICE_BINDING_1_TOML (SERVICE_NAME_1_TOML), SERVICE_BINDING_2_TOML (SERVICE_NAME_2_TOML) - Your worker has access to the following bindings: - - Durable Objects: - - DO_BINDING_1_TOML: NEW_DO_1 (defined in NEW_DO_SCRIPT_1) - - DO_BINDING_2_TOML: DO_2_TOML (defined in DO_SCRIPT_2_TOML) - - DO_BINDING_3_ARGS: DO_3_ARGS (defined in DO_SCRIPT_3_ARGS) - - KV Namespaces: - - KV_BINDING_1_TOML: NEW_KV_ID_1 - - KV_BINDING_2_TOML: KV_ID_2_TOML - - KV_BINDING_3_ARGS: KV_ID_3_ARGS - - D1 Databases: - - D1_BINDING_1_TOML: local-D1_BINDING_1_TOML=NEW_D1_NAME_1 (NEW_D1_NAME_1) - - D1_BINDING_2_TOML: D1_NAME_2_TOML (D1_ID_2_TOML) - - D1_BINDING_3_ARGS: local-D1_BINDING_3_ARGS=D1_NAME_3_ARGS (D1_NAME_3_ARGS) - - R2 Buckets: - - R2_BINDING_1_TOML: NEW_R2_BUCKET_1 - - R2_BINDING_2_TOML: R2_BUCKET_2_TOML - - R2_BINDING_3_TOML: R2_BUCKET_3_ARGS - - Services: - - SERVICE_BINDING_1_TOML: NEW_SERVICE_NAME_1 - - SERVICE_BINDING_2_TOML: SERVICE_NAME_2_TOML - - SERVICE_BINDING_3_TOML: SERVICE_NAME_3_ARGS - - AI: - - Name: AI_BINDING_2_TOML - - Vars: - - VAR1: "(hidden)" - - VAR2: "VAR_2_TOML" - - VAR3: "(hidden)" - ▲ [WARNING] ⎔ Support for service bindings in local mode is experimental and may change. - ▲ [WARNING] ⎔ Support for external Durable Objects in local mode is experimental and may change. - " - `); + expect(prestartOutput).toMatchSnapshot(); }); it("should pick up wrangler.toml configuration even in cases when `pages_build_output_dir` was not specified, but the command argument was", async () => { @@ -491,13 +451,10 @@ describe("pages dev", () => { }); const port = await getPort(); - const worker = helper.runLongLived( - `wrangler pages dev --port ${port} public` - ); + const worker = helper.runLongLived(`${cmd} --port ${port} public`); const { url } = await worker.waitForReady(); - - await expect(fetchText(url)).resolves.toMatchInlineSnapshot( - `"⚡️ Pages supports wrangler.toml ⚡️"` + await expect(fetchText(url)).resolves.toBe( + "⚡️ Pages supports wrangler.toml ⚡️" ); }); @@ -517,7 +474,7 @@ describe("pages dev", () => { const { url } = await worker.waitForReady(); let text = await fetchText(url); - expect(text).toMatchInlineSnapshot('"Hello World!"'); + expect(text).toBe("Hello World!"); await helper.seed({ "functions/_middleware.js": dedent` @@ -529,7 +486,7 @@ describe("pages dev", () => { await worker.waitForReload(); text = await fetchText(url); - expect(text).toMatchInlineSnapshot('"Updated Worker!"'); + expect(text).toBe("Updated Worker!"); }); it("should support modifying dependencies during dev session (Functions)", async () => { @@ -557,10 +514,10 @@ describe("pages dev", () => { const { url } = await worker.waitForReady(); let hello = await fetchText(`${url}/greetings/hello`); - expect(hello).toMatchInlineSnapshot('"Hello World!"'); + expect(hello).toBe("Hello World!"); let hi = await fetchText(`${url}/hi`); - expect(hi).toMatchInlineSnapshot('"Hi there!"'); + expect(hi).toBe("Hi there!"); await helper.seed({ "utils/greetings.js": dedent` @@ -572,10 +529,10 @@ describe("pages dev", () => { await worker.waitForReload(); hello = await fetchText(`${url}/greetings/hello`); - expect(hello).toMatchInlineSnapshot('"Hey World!"'); + expect(hello).toBe("Hey World!"); hi = await fetchText(`${url}/hi`); - expect(hi).toMatchInlineSnapshot('"Hey there!"'); + expect(hi).toBe("Hey there!"); }); it("should support modifying external modules during dev session (Functions)", async () => { @@ -597,7 +554,7 @@ describe("pages dev", () => { const { url } = await worker.waitForReady(); let hello = await fetchText(`${url}/hello`); - expect(hello).toMatchInlineSnapshot('"

Hello HTML World!

"'); + expect(hello).toBe("

Hello HTML World!

"); await helper.seed({ "modules/my-html.html": dedent` @@ -608,7 +565,7 @@ describe("pages dev", () => { await worker.waitForReload(); hello = await fetchText(`${url}/hello`); - expect(hello).toMatchInlineSnapshot('"

Updated HTML!

"'); + expect(hello).toBe("

Updated HTML!

"); }); it("should modify worker during dev session (_worker)", async () => { @@ -628,7 +585,7 @@ describe("pages dev", () => { const { url } = await worker.waitForReady(); let hello = await fetchText(url); - expect(hello).toMatchInlineSnapshot('"Hello World!"'); + expect(hello).toBe("Hello World!"); await helper.seed({ "_worker.js": dedent` @@ -642,7 +599,7 @@ describe("pages dev", () => { await worker.waitForReload(); hello = await fetchText(url); - expect(hello).toMatchInlineSnapshot('"Updated Worker!"'); + expect(hello).toBe("Updated Worker!"); }); it("should support modifying dependencies during dev session (_worker)", async () => { @@ -666,7 +623,7 @@ describe("pages dev", () => { const { url } = await worker.waitForReady(); let bear = await fetchText(url); - expect(bear).toMatchInlineSnapshot('"BEAR!"'); + expect(bear).toBe("BEAR!"); await helper.seed({ "pets/bear.js": dedent` @@ -677,7 +634,7 @@ describe("pages dev", () => { await worker.waitForReload(); bear = await fetchText(url); - expect(bear).toMatchInlineSnapshot('"We love BEAR!"'); + expect(bear).toBe("We love BEAR!"); }); it("should support modifying external modules during dev session (_worker)", async () => { @@ -701,7 +658,7 @@ describe("pages dev", () => { const { url } = await worker.waitForReady(); let graham = await fetchText(url); - expect(graham).toMatchInlineSnapshot('"

Graham the dog

"'); + expect(graham).toBe("

Graham the dog

"); await helper.seed({ "graham.html": dedent` @@ -712,9 +669,7 @@ describe("pages dev", () => { await worker.waitForReload(); graham = await fetchText(url); - expect(graham).toMatchInlineSnapshot( - '"

Graham is the bestest doggo

"' - ); + expect(graham).toBe("

Graham is the bestest doggo

"); }); it("should support modifying _routes.json during dev session", async () => { @@ -750,10 +705,10 @@ describe("pages dev", () => { const { url } = await worker.waitForReady(); const foo = await fetchText(`${url}/foo`); - expect(foo).toMatchInlineSnapshot('"foo"'); + expect(foo).toBe("foo"); const bar = await fetchText(`${url}/bar`); - expect(bar).toMatchInlineSnapshot('"bar"'); + expect(bar).toBe("bar"); await helper.seed({ "_routes.json": dedent` @@ -767,10 +722,10 @@ describe("pages dev", () => { await worker.waitForReload(); const foo2 = await fetchText(`${url}/foo`); - expect(foo2).toMatchInlineSnapshot('"foo"'); + expect(foo2).toBe("foo"); const bar2 = await fetchText(`${url}/bar`); - expect(bar2).toMatchInlineSnapshot('"hello world"'); + expect(bar2).toBe("hello world"); }); }); }); diff --git a/packages/wrangler/src/__tests__/pages/pages.test.ts b/packages/wrangler/src/__tests__/pages/pages.test.ts index a9187c3f0108..913b4d354fa6 100644 --- a/packages/wrangler/src/__tests__/pages/pages.test.ts +++ b/packages/wrangler/src/__tests__/pages/pages.test.ts @@ -77,6 +77,7 @@ describe("pages", () => { --persist-to Specify directory to use for local persistence (defaults to .wrangler/state) [string] --log-level Specify logging level [choices: \\"debug\\", \\"info\\", \\"log\\", \\"warn\\", \\"error\\", \\"none\\"] --show-interactive-dev-session Show interactive dev session (defaults to true if the terminal supports interactivity) [boolean] + --experimental-dev-env, --x-dev-env Use the experimental DevEnv instantiation (unified across wrangler dev and unstable_dev) [boolean] [default: false] --experimental-registry, --x-registry Use the experimental file based dev registry for multi-worker development [boolean] [default: false]" `); }); diff --git a/packages/wrangler/src/dev.tsx b/packages/wrangler/src/dev.tsx index a405ba0af7dc..6cc9b4cbd11e 100644 --- a/packages/wrangler/src/dev.tsx +++ b/packages/wrangler/src/dev.tsx @@ -519,6 +519,32 @@ async function updateDevEnvRegistry( }); } +async function getPagesAssetsFetcher( + options: EnablePagesAssetsServiceBindingOptions | undefined +): Promise { + if (options !== undefined) { + // `./miniflare-cli/assets` dynamically imports`@cloudflare/pages-shared/environment-polyfills`. + // `@cloudflare/pages-shared/environment-polyfills/types.ts` defines `global` + // augmentations that pollute the `import`-site's typing environment. + // + // We `require` instead of `import`ing here to avoid polluting the main + // `wrangler` TypeScript project with the `global` augmentations. This + // relies on the fact that `require` is untyped. + // + // eslint-disable-next-line @typescript-eslint/no-var-requires + const generateASSETSBinding = require("./miniflare-cli/assets").default; + return { + ASSETS: { + type: "fetcher", + fetcher: await generateASSETSBinding({ + log: logger, + ...options, + }), + }, + }; + } +} + export async function startDev(args: StartDevOptions) { let watcher: ReturnType | undefined; let rerender: (node: React.ReactNode) => void | undefined; @@ -655,6 +681,9 @@ export async function startDev(args: StartDevOptions) { }), }, bindings: { + ...(await getPagesAssetsFetcher( + args.enablePagesAssetsServiceBinding + )), ...collectPlainTextVars(args.var), ...convertCfWorkerInitBindingstoBindings({ kv_namespaces: args.kv, diff --git a/packages/wrangler/src/pages/dev.ts b/packages/wrangler/src/pages/dev.ts index 174640de06c8..b5a2e9c106a8 100644 --- a/packages/wrangler/src/pages/dev.ts +++ b/packages/wrangler/src/pages/dev.ts @@ -237,6 +237,13 @@ export function Options(yargs: CommonYargsArgv) { "Show interactive dev session (defaults to true if the terminal supports interactivity)", type: "boolean", }, + "experimental-dev-env": { + alias: ["x-dev-env"], + type: "boolean", + describe: + "Use the experimental DevEnv instantiation (unified across wrangler dev and unstable_dev)", + default: false, + }, "experimental-registry": { alias: ["x-registry"], type: "boolean", @@ -899,6 +906,7 @@ export const Handler = async (args: PagesDevArguments) => { testMode: false, watch: true, fileBasedRegistry: args.experimentalRegistry, + devEnv: args.experimentalDevEnv, }, }); await metrics.sendMetricsEvent("run pages dev");