diff --git a/.changeset/happy-tools-approve.md b/.changeset/happy-tools-approve.md new file mode 100644 index 000000000000..5937ae9d7107 --- /dev/null +++ b/.changeset/happy-tools-approve.md @@ -0,0 +1,14 @@ +--- +"wrangler": minor +--- + +feat: allow preserving file names when defining rules for non-js modules + +The developer is now able to specify the `preserve_file_names property in wrangler.toml +which specifies whether Wrangler will preserve the file names additional modules that are +added to the deployment bundle of a Worker. + +If not set to true, files will be named using the pattern ${fileHash}-${basename}. +For example, `34de60b44167af5c5a709e62a4e20c4f18c9e3b6-favicon.ico`. + +Resolves [#4741](https://github.com/cloudflare/workers-sdk/issues/4741) diff --git a/packages/wrangler/src/__tests__/deploy.test.ts b/packages/wrangler/src/__tests__/deploy.test.ts index ea8a61bd4630..dc5843ef112b 100644 --- a/packages/wrangler/src/__tests__/deploy.test.ts +++ b/packages/wrangler/src/__tests__/deploy.test.ts @@ -7418,6 +7418,69 @@ addEventListener('fetch', event => {});` `); }); + it("should be able to preserve file names when defining rules for uploading non-js modules (sw)", async () => { + writeWranglerToml({ + rules: [{ type: "Text", globs: ["**/*.file"], fallthrough: true }], + preserve_file_names: true, + }); + fs.writeFileSync("./index.js", `import TEXT from './text.file';`); + fs.writeFileSync("./text.file", "SOME TEXT CONTENT"); + mockSubDomainRequest(); + mockUploadWorkerRequest({ + expectedType: "sw", + expectedBindings: [ + { + name: "__text_file", + part: "__text_file", + type: "text_blob", + }, + ], + expectedModules: { + __text_file: "SOME TEXT CONTENT", + }, + }); + await runWrangler("deploy index.js"); + expect(std.out).toMatchInlineSnapshot(` + "Total Upload: xx KiB / gzip: xx KiB + Uploaded test-name (TIMINGS) + Published test-name (TIMINGS) + https://test-name.test-sub-domain.workers.dev + Current Deployment ID: Galaxy-Class" + `); + expect(std.err).toMatchInlineSnapshot(`""`); + expect(std.warn).toMatchInlineSnapshot(`""`); + }); + + it("should be able to preserve file names when defining rules for uploading non-js modules (esm)", async () => { + writeWranglerToml({ + rules: [{ type: "Text", globs: ["**/*.file"], fallthrough: true }], + preserve_file_names: true, + }); + fs.writeFileSync( + "./index.js", + `import TEXT from './text.file'; export default {};` + ); + fs.writeFileSync("./text.file", "SOME TEXT CONTENT"); + mockSubDomainRequest(); + mockUploadWorkerRequest({ + expectedType: "esm", + expectedBindings: [], + expectedModules: { + "./text.file": "SOME TEXT CONTENT", + }, + }); + await runWrangler("deploy index.js"); + expect(std.out).toMatchInlineSnapshot(` + "Total Upload: xx KiB / gzip: xx KiB + Uploaded test-name (TIMINGS) + Published test-name (TIMINGS) + https://test-name.test-sub-domain.workers.dev + Current Deployment ID: Galaxy-Class" + `); + expect(std.err).toMatchInlineSnapshot(`""`); + expect(std.warn).toMatchInlineSnapshot(`""`); + }); + describe("inject process.env.NODE_ENV", () => { let actualProcessEnvNodeEnv: string | undefined; beforeEach(() => { diff --git a/packages/wrangler/src/config/environment.ts b/packages/wrangler/src/config/environment.ts index b7057b43cdc5..613277e19a98 100644 --- a/packages/wrangler/src/config/environment.ts +++ b/packages/wrangler/src/config/environment.ts @@ -93,6 +93,14 @@ interface EnvironmentInheritable { */ find_additional_modules: boolean | undefined; + /** + * Determines whether Wrangler will preserve bundled file names. + * Defaults to false. + * If left unset, files will be named using the pattern ${fileHash}-${basename}, + * for example, `34de60b44167af5c5a709e62a4e20c4f18c9e3b6-favicon.ico`. + */ + preserve_file_names: boolean | undefined; + /** * The directory in which module rules should be evaluated when including additional files into a worker deployment. * This defaults to the directory containing the `main` entry point of the worker if not specified. diff --git a/packages/wrangler/src/config/validation.ts b/packages/wrangler/src/config/validation.ts index 4ef791f213ec..570d61096612 100644 --- a/packages/wrangler/src/config/validation.ts +++ b/packages/wrangler/src/config/validation.ts @@ -1154,6 +1154,14 @@ function normalizeAndValidateEnvironment( isBoolean, undefined ), + preserve_file_names: inheritable( + diagnostics, + topLevelEnv, + rawEnv, + "preserve_file_names", + isBoolean, + undefined + ), base_dir: normalizeAndValidateBaseDirField( configPath, inheritable( diff --git a/packages/wrangler/src/deploy/deploy.ts b/packages/wrangler/src/deploy/deploy.ts index c853a7f4d03d..012adaa595ea 100644 --- a/packages/wrangler/src/deploy/deploy.ts +++ b/packages/wrangler/src/deploy/deploy.ts @@ -481,6 +481,7 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m // `findAdditionalModules` always defaults to `false` findAdditionalModules: config.find_additional_modules ?? false, rules: props.rules, + preserveFileNames: config.preserve_file_names ?? false, }); const { modules, dependencies, resolvedEntryPointPath, bundleType } = diff --git a/packages/wrangler/src/deployment-bundle/module-collection.ts b/packages/wrangler/src/deployment-bundle/module-collection.ts index 97218dee50d2..2f9ba47ce5c6 100644 --- a/packages/wrangler/src/deployment-bundle/module-collection.ts +++ b/packages/wrangler/src/deployment-bundle/module-collection.ts @@ -223,7 +223,9 @@ export function createModuleCollector(props: { .createHash("sha1") .update(fileContent) .digest("hex"); - const fileName = `./${fileHash}-${path.basename(args.path)}`; + const fileName = props.preserveFileNames + ? args.path + : `./${fileHash}-${path.basename(args.path)}`; const { rule } = rulesMatchers.find(({ regex }) => regex.test(fileName)) || {}; @@ -338,7 +340,7 @@ export function createModuleCollector(props: { .update(fileContent) .digest("hex"); const fileName = props.preserveFileNames - ? filePath + ? args.path : `./${fileHash}-${path.basename(args.path)}`; // add the module to the array