Skip to content

Commit 00a8590

Browse files
mrbbotpetebacondarwin
authored andcommitted
allow __STATIC_CONTENT_MANIFEST to be imported from any module
1 parent d3a758c commit 00a8590

File tree

3 files changed

+90
-6
lines changed

3 files changed

+90
-6
lines changed

.changeset/hot-deers-return.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"wrangler": patch
3+
---
4+
5+
fix: allow `__STATIC_CONTENT_MANIFEST` module to be imported anywhere
6+
7+
`__STATIC_CONTENT_MANIFEST` can now be imported in subdirectories when
8+
`--no-bundle` or `find_additional_modules` are enabled.

packages/wrangler/src/__tests__/deploy.test.ts

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2199,8 +2199,10 @@ addEventListener('fetch', event => {});`
21992199

22002200
it("when using a module worker type, it should add an asset manifest module, and bind to a namespace", async () => {
22012201
const assets = [
2202-
{ filePath: "file-1.txt", content: "Content of file-1" },
2203-
{ filePath: "file-2.txt", content: "Content of file-2" },
2202+
// Using `.text` extension instead of `.txt` means files won't be
2203+
// treated as additional modules
2204+
{ filePath: "file-1.text", content: "Content of file-1" },
2205+
{ filePath: "file-2.text", content: "Content of file-2" },
22042206
];
22052207
const kvNamespace = {
22062208
title: "__test-name-workers_sites_assets",
@@ -2211,8 +2213,27 @@ addEventListener('fetch', event => {});`
22112213
site: {
22122214
bucket: "assets",
22132215
},
2216+
find_additional_modules: true,
2217+
rules: [{ type: "ESModule", globs: ["**/*.mjs"] }],
22142218
});
22152219
writeWorkerSource({ type: "esm" });
2220+
fs.mkdirSync("a/b/c", { recursive: true });
2221+
fs.writeFileSync(
2222+
"a/1.mjs",
2223+
'export { default } from "__STATIC_CONTENT_MANIFEST";'
2224+
);
2225+
fs.writeFileSync(
2226+
"a/b/2.mjs",
2227+
'export { default } from "__STATIC_CONTENT_MANIFEST";'
2228+
);
2229+
fs.writeFileSync(
2230+
"a/b/3.mjs",
2231+
'export { default } from "__STATIC_CONTENT_MANIFEST";'
2232+
);
2233+
fs.writeFileSync(
2234+
"a/b/c/4.mjs",
2235+
'export { default } from "__STATIC_CONTENT_MANIFEST";'
2236+
);
22162237
writeAssets(assets);
22172238
mockUploadWorkerRequest({
22182239
expectedBindings: [
@@ -2224,7 +2245,13 @@ addEventListener('fetch', event => {});`
22242245
],
22252246
expectedModules: {
22262247
__STATIC_CONTENT_MANIFEST:
2227-
'{"file-1.txt":"file-1.2ca234f380.txt","file-2.txt":"file-2.5938485188.txt"}',
2248+
'{"file-1.text":"file-1.2ca234f380.text","file-2.text":"file-2.5938485188.text"}',
2249+
"a/__STATIC_CONTENT_MANIFEST":
2250+
'export { default } from "../__STATIC_CONTENT_MANIFEST";',
2251+
"a/b/__STATIC_CONTENT_MANIFEST":
2252+
'export { default } from "../../__STATIC_CONTENT_MANIFEST";',
2253+
"a/b/c/__STATIC_CONTENT_MANIFEST":
2254+
'export { default } from "../../../__STATIC_CONTENT_MANIFEST";',
22282255
},
22292256
});
22302257
mockSubDomainRequest();
@@ -2235,10 +2262,15 @@ addEventListener('fetch', event => {});`
22352262
await runWrangler("deploy");
22362263

22372264
expect(std.info).toMatchInlineSnapshot(`
2238-
"Fetching list of already uploaded assets...
2265+
"Attaching additional modules:
2266+
- a/1.mjs (esm)
2267+
- a/b/2.mjs (esm)
2268+
- a/b/3.mjs (esm)
2269+
- a/b/c/4.mjs (esm)
2270+
Fetching list of already uploaded assets...
22392271
Building list of assets to upload...
2240-
+ file-1.2ca234f380.txt (uploading new version of file-1.txt)
2241-
+ file-2.5938485188.txt (uploading new version of file-2.txt)
2272+
+ file-1.2ca234f380.text (uploading new version of file-1.text)
2273+
+ file-2.5938485188.text (uploading new version of file-2.text)
22422274
Uploading 2 new assets...
22432275
Uploaded 100% [2 out of 2]"
22442276
`);

packages/wrangler/src/deployment-bundle/create-worker-upload-form.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import assert from "node:assert";
12
import { readFileSync } from "node:fs";
3+
import path from "node:path";
24
import { FormData, File } from "undici";
35
import { handleUnsafeCapnp } from "./capnp";
46
import type {
@@ -294,6 +296,48 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
294296
);
295297
}
296298

299+
const manifestModuleName = "__STATIC_CONTENT_MANIFEST";
300+
const hasManifest = modules?.some(({ name }) => name === manifestModuleName);
301+
if (hasManifest && main.type === "esm") {
302+
assert(modules !== undefined);
303+
// Each modules-format worker has a virtual file system for module
304+
// resolution. For example, uploading modules with names `1.mjs`,
305+
// `a/2.mjs` and `a/b/3.mjs`, creates virtual directories `a` and `a/b`.
306+
// `1.mjs` is in the virtual root directory.
307+
//
308+
// The above code adds the `__STATIC_CONTENT_MANIFEST` module to the root
309+
// directory. This means `import manifest from "__STATIC_CONTENT_MANIFEST"`
310+
// will only work if the importing module is also in the root. If the
311+
// importing module was `a/b/3.mjs` for example, the import would need to
312+
// be `import manifest from "../../__STATIC_CONTENT_MANIFEST"`.
313+
//
314+
// When Wrangler bundles all user code, this isn't a problem, as code is
315+
// only ever uploaded to the root. However, once `--no-bundle` or
316+
// `find_additional_modules` is enabled, the user controls the directory
317+
// structure.
318+
//
319+
// To fix this, if we've got a modules-format worker, we add stub modules
320+
// in each subdirectory that re-export the manifest module from the root.
321+
// This allows the manifest to be imported as `__STATIC_CONTENT_MANIFEST`
322+
// in every directory, whilst avoiding duplication of the manifest.
323+
324+
// Collect unique subdirectories
325+
const subDirs = new Set(
326+
modules.map((module) => path.posix.dirname(module.name))
327+
);
328+
for (const subDir of subDirs) {
329+
// Ignore `.` as it's not a subdirectory, and we don't want to
330+
// register the manifest module in the root twice.
331+
if (subDir === ".") continue;
332+
const relativePath = path.posix.relative(subDir, manifestModuleName);
333+
modules.push({
334+
name: path.posix.join(subDir, manifestModuleName),
335+
content: `export { default } from ${JSON.stringify(relativePath)};`,
336+
type: "esm",
337+
});
338+
}
339+
}
340+
297341
if (main.type === "commonjs") {
298342
// This is a service-worker format worker.
299343
for (const module of Object.values([...(modules || [])])) {

0 commit comments

Comments
 (0)