Skip to content

Commit 8e38442

Browse files
fix: resolve raw file bindings correctly in wrangler dev local mode (#756)
For `wasm_modules`/`text_blobs`/`data_blobs` in local mode, we need to rewrite the paths as absolute so that they're resolved correctly by miniflare. This also expands some coverage for local mode `wrangler dev`. Fixes #740 Fixes #416
1 parent 6d43e94 commit 8e38442

File tree

14 files changed

+228
-17
lines changed

14 files changed

+228
-17
lines changed

.changeset/flat-ads-flash.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
"wrangler": patch
3+
---
4+
5+
fix: resolve raw file bindings correctly in `wrangler dev` local mode
6+
7+
For `wasm_modules`/`text_blobs`/`data_blobs` in local mode, we need to rewrite the paths as absolute so that they're resolved correctly by miniflare. This also expands some coverage for local mode `wrangler dev`.
8+
9+
Fixes https://github.com/cloudflare/wrangler2/issues/740
10+
Fixes https://github.com/cloudflare/wrangler2/issues/416

examples/local-mode-tests/package.json

+4
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@
55
"description": "",
66
"main": "index.js",
77
"scripts": {
8+
"check:type": "tsc",
89
"test": "npx jest --forceExit"
910
},
11+
"devDependencies": {
12+
"@cloudflare/workers-types": "^3.2.0"
13+
},
1014
"keywords": [],
1115
"author": "",
1216
"license": "ISC",
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Here be some data
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Here be some text

examples/local-mode-tests/src/index.ts

-5
This file was deleted.
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// @ts-expect-error non standard module
2+
import data from "../some-data.bin";
3+
// @ts-expect-error non standard module
4+
import text from "../some-text.txt";
5+
6+
export default {
7+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
8+
async fetch(_request: Request, env: any): Promise<Response> {
9+
return new Response(
10+
JSON.stringify(
11+
{
12+
VAR1: env.VAR1,
13+
VAR2: env.VAR2,
14+
VAR3: env.VAR3,
15+
text,
16+
data: new TextDecoder().decode(data),
17+
},
18+
null,
19+
2
20+
)
21+
);
22+
},
23+
};

examples/local-mode-tests/src/sw.ts

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// @ts-expect-error non standard module
2+
import data from "../some-data.bin";
3+
// @ts-expect-error non standard module
4+
import text from "../some-text.txt";
5+
6+
addEventListener("fetch", (event: FetchEvent) => {
7+
event.respondWith(handleRequest(event.request));
8+
});
9+
10+
async function handleRequest(_req: Request): Promise<Response> {
11+
return new Response(
12+
JSON.stringify(
13+
{
14+
// @ts-expect-error binding
15+
VAR1,
16+
// @ts-expect-error binding
17+
VAR2,
18+
// @ts-expect-error binding
19+
VAR3,
20+
text,
21+
data: new TextDecoder().decode(data),
22+
// @ts-expect-error binding
23+
TEXT,
24+
// @ts-expect-error binding
25+
DATA: new TextDecoder().decode(DATA),
26+
},
27+
null,
28+
2
29+
)
30+
);
31+
}
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
name = "local-mode-tests"
2-
main = "src/index.ts"
32
compatibility_date = "2022-03-27"
3+
4+
[vars]
5+
VAR1 = "value1"
6+
VAR2 = 123
7+
VAR3 = {abc = "def"}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name = "local-mode-tests"
2+
compatibility_date = "2022-03-27"
3+
4+
[vars]
5+
VAR1 = "value1"
6+
VAR2 = 123
7+
VAR3 = {abc = "def"}
8+
9+
[text_blobs]
10+
TEXT = "../some-text.txt"
11+
12+
[data_blobs]
13+
DATA = "../some-data.bin"

examples/local-mode-tests/tests/index.test.ts renamed to examples/local-mode-tests/tests/module.test.ts

+29-5
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,23 @@ const isWindows = process.platform === "win32";
2121
let wranglerProcess: ChildProcess;
2222

2323
beforeAll(async () => {
24-
wranglerProcess = spawn("npx", ["wrangler", "dev", "--local"], {
25-
shell: isWindows,
26-
});
24+
wranglerProcess = spawn(
25+
"npx",
26+
[
27+
"wrangler",
28+
"dev",
29+
"src/module.ts",
30+
"--local",
31+
"--config",
32+
"src/wrangler.module.toml",
33+
"--port",
34+
"9001",
35+
],
36+
{
37+
shell: isWindows,
38+
stdio: "inherit",
39+
}
40+
);
2741
});
2842

2943
afterAll(async () => {
@@ -40,7 +54,17 @@ afterAll(async () => {
4054
});
4155

4256
it("renders", async () => {
43-
const response = await waitUntilReady("http://localhost:8787/");
57+
const response = await waitUntilReady("http://localhost:9001/");
4458
const text = await response.text();
45-
expect(text).toContain("Hello World!");
59+
expect(text).toMatchInlineSnapshot(`
60+
"{
61+
\\"VAR1\\": \\"value1\\",
62+
\\"VAR2\\": 123,
63+
\\"VAR3\\": {
64+
\\"abc\\": \\"def\\"
65+
},
66+
\\"text\\": \\"Here be some text\\",
67+
\\"data\\": \\"Here be some data\\"
68+
}"
69+
`);
4670
});
+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { spawn } from "child_process";
2+
import { fetch } from "undici";
3+
import type { ChildProcess } from "child_process";
4+
import type { Response } from "undici";
5+
6+
const waitUntilReady = async (url: string): Promise<Response> => {
7+
let response: Response | undefined = undefined;
8+
9+
while (response === undefined) {
10+
await new Promise((resolvePromise) => setTimeout(resolvePromise, 100));
11+
12+
try {
13+
response = await fetch(url);
14+
} catch {}
15+
}
16+
17+
return response as Response;
18+
};
19+
const isWindows = process.platform === "win32";
20+
21+
let wranglerProcess: ChildProcess;
22+
23+
beforeAll(async () => {
24+
wranglerProcess = spawn(
25+
"npx",
26+
[
27+
"wrangler",
28+
"dev",
29+
"src/sw.ts",
30+
"--local",
31+
"--config",
32+
"src/wrangler.sw.toml",
33+
"--port",
34+
"9002",
35+
],
36+
{
37+
shell: isWindows,
38+
stdio: "inherit",
39+
}
40+
);
41+
});
42+
43+
afterAll(async () => {
44+
await new Promise((resolve, reject) => {
45+
wranglerProcess.once("exit", (code) => {
46+
if (!code) {
47+
resolve(code);
48+
} else {
49+
reject(code);
50+
}
51+
});
52+
wranglerProcess.kill();
53+
});
54+
});
55+
56+
it("renders", async () => {
57+
const response = await waitUntilReady("http://localhost:9002/");
58+
const text = await response.text();
59+
expect(text).toMatchInlineSnapshot(`
60+
"{
61+
\\"VAR1\\": \\"value1\\",
62+
\\"VAR2\\": 123,
63+
\\"VAR3\\": {
64+
\\"abc\\": \\"def\\"
65+
},
66+
\\"text\\": \\"Here be some text\\",
67+
\\"data\\": \\"Here be some data\\",
68+
\\"TEXT\\": \\"Here be some text\\",
69+
\\"DATA\\": \\"Here be some data\\"
70+
}"
71+
`);
72+
});

examples/local-mode-tests/tsconfig.json

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"target": "esnext",
1010
"strict": true,
1111
"noEmit": true,
12+
"types": ["@cloudflare/workers-types", "jest"],
1213
"skipLibCheck": true
1314
}
1415
}

package-lock.json

+8-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/wrangler/src/dev/local.tsx

+30-4
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,35 @@ function useLocalWorker({
8383

8484
const scriptPath = realpathSync(bundle.path);
8585

86-
const wasmBindings = { ...bindings.wasm_modules };
87-
const textBlobBindings = { ...bindings.text_blobs };
88-
const dataBlobBindings = { ...bindings.data_blobs };
86+
// the wasm_modules/text_blobs/data_blobs bindings are
87+
// relative to process.cwd(), but the actual worker bundle
88+
// is in the temp output directory; so we rewrite the paths to be absolute,
89+
// letting miniflare resolve them correctly
90+
91+
// wasm
92+
const wasmBindings: Record<string, string> = {};
93+
for (const [name, filePath] of Object.entries(
94+
bindings.wasm_modules || {}
95+
)) {
96+
wasmBindings[name] = path.join(process.cwd(), filePath);
97+
}
98+
99+
// text
100+
const textBlobBindings: Record<string, string> = {};
101+
for (const [name, filePath] of Object.entries(
102+
bindings.text_blobs || {}
103+
)) {
104+
textBlobBindings[name] = path.join(process.cwd(), filePath);
105+
}
106+
107+
// data
108+
const dataBlobBindings: Record<string, string> = {};
109+
for (const [name, filePath] of Object.entries(
110+
bindings.data_blobs || {}
111+
)) {
112+
dataBlobBindings[name] = path.join(process.cwd(), filePath);
113+
}
114+
89115
if (format === "service-worker") {
90116
for (const { type, name } of bundle.modules) {
91117
if (type === "compiled-wasm") {
@@ -187,7 +213,7 @@ function useLocalWorker({
187213
});
188214

189215
local.current.stdout?.on("data", (data: Buffer) => {
190-
console.log(`${data.toString()}`);
216+
process.stdout.write(data);
191217
});
192218

193219
local.current.stderr?.on("data", (data: Buffer) => {

0 commit comments

Comments
 (0)