diff --git a/.changeset/long-mugs-pull.md b/.changeset/long-mugs-pull.md new file mode 100644 index 000000000000..6167bf940c89 --- /dev/null +++ b/.changeset/long-mugs-pull.md @@ -0,0 +1,20 @@ +--- +"wrangler": minor +--- + +feat: add `config.keep_names` option + +Adds a new option to Wrangler to allow developers to opt out of esbuild's `keep_names` option (https://esbuild.github.io/api/#keep-names). By default, Wrangler sets this to `true` + +This is something developers should not usually need to care about, but sometimes +`keep_names` can create issues, and in such cases they will be now able to opt-out. + +Example `wrangler.jsonc`: + +```json +{ + "name": "my-worker", + "main": "src/worker.ts", + "keep_names": false +} +``` diff --git a/packages/wrangler/src/__tests__/deploy.test.ts b/packages/wrangler/src/__tests__/deploy.test.ts index 6d96d6554687..0c128e31dbf4 100644 --- a/packages/wrangler/src/__tests__/deploy.test.ts +++ b/packages/wrangler/src/__tests__/deploy.test.ts @@ -6571,6 +6571,84 @@ addEventListener('fetch', event => {});` `); expect(std.err).toMatchInlineSnapshot(`""`); }); + + it("should apply esbuild's keep-names functionality by default", async () => { + writeWranglerConfig({ + main: "./index.js", + legacy_env: false, + env: { + testEnv: {}, + }, + }); + fs.writeFileSync( + "./index.js", + ` + export + default { + fetch() { + function sayHello() { + return "Hello World with keep_names"; + } + return new Response(sayHello()); + } + } + ` + ); + + const underscoreUnderscoreNameRegex = /__name\(.*?\)/; + + mockUploadWorkerRequest({ + env: "testEnv", + expectedType: "esm", + legacyEnv: false, + expectedEntry: (str) => { + expect(str).toMatch(underscoreUnderscoreNameRegex); + }, + }); + + mockSubDomainRequest(); + await runWrangler("deploy -e testEnv index.js"); + }); + + it("should apply esbuild's keep-names functionality unless keep_names is set to false", async () => { + writeWranglerConfig({ + main: "./index.js", + legacy_env: false, + env: { + testEnv: { + keep_names: false, + }, + }, + }); + fs.writeFileSync( + "./index.js", + ` + export + default { + fetch() { + function sayHello() { + return "Hello World without keep_names"; + } + return new Response(sayHello()); + } + } + ` + ); + + const underscoreUnderscoreNameRegex = /__name\(.*?\)/; + + mockUploadWorkerRequest({ + env: "testEnv", + expectedType: "esm", + legacyEnv: false, + expectedEntry: (str) => { + expect(str).not.toMatch(underscoreUnderscoreNameRegex); + }, + }); + + mockSubDomainRequest(); + await runWrangler("deploy -e testEnv index.js"); + }); }); describe("durable object migrations", () => { diff --git a/packages/wrangler/src/api/startDevWorker/BundlerController.ts b/packages/wrangler/src/api/startDevWorker/BundlerController.ts index 09cd0679db49..92ff22158368 100644 --- a/packages/wrangler/src/api/startDevWorker/BundlerController.ts +++ b/packages/wrangler/src/api/startDevWorker/BundlerController.ts @@ -117,6 +117,7 @@ export class BundlerController extends Controller { jsxFragment: config.build.jsxFactory, tsconfig: config.build.tsconfig, minify: config.build.minify, + keepNames: config.build.keepNames ?? true, nodejsCompatMode: config.build.nodejsCompatMode, define: config.build.define, checkFetch: shouldCheckFetch( @@ -246,6 +247,7 @@ export class BundlerController extends Controller { rules: config.build.moduleRules, tsconfig: config.build?.tsconfig, minify: config.build?.minify, + keepNames: config.build?.keepNames ?? true, nodejsCompatMode: config.build.nodejsCompatMode, define: config.build.define, alias: config.build.alias, diff --git a/packages/wrangler/src/api/startDevWorker/ConfigController.ts b/packages/wrangler/src/api/startDevWorker/ConfigController.ts index 668ed20b9962..2bf8a0a714b6 100644 --- a/packages/wrangler/src/api/startDevWorker/ConfigController.ts +++ b/packages/wrangler/src/api/startDevWorker/ConfigController.ts @@ -289,6 +289,7 @@ async function resolveConfig( moduleRules: input.build?.moduleRules ?? getRules(config), minify: input.build?.minify ?? config.minify, + keepNames: input.build?.keepNames ?? config.keep_names, define: { ...config.define, ...input.build?.define }, custom: { command: input.build?.custom?.command ?? config.build?.command, diff --git a/packages/wrangler/src/api/startDevWorker/types.ts b/packages/wrangler/src/api/startDevWorker/types.ts index e4371c25c3f7..734d89f03f8e 100644 --- a/packages/wrangler/src/api/startDevWorker/types.ts +++ b/packages/wrangler/src/api/startDevWorker/types.ts @@ -108,6 +108,8 @@ export interface StartDevWorkerInput { alias?: Record; /** Whether the bundled worker is minified. Only takes effect if bundle: true. */ minify?: boolean; + /** Whether to keep function names after JavaScript transpilations. */ + keepNames?: boolean; /** Options controlling a custom build step. */ custom?: { /** Custom shell command to run before bundling. Runs even if bundle. */ diff --git a/packages/wrangler/src/config/config.ts b/packages/wrangler/src/config/config.ts index d5bf88e8b63b..ef9bb45ef827 100644 --- a/packages/wrangler/src/config/config.ts +++ b/packages/wrangler/src/config/config.ts @@ -332,6 +332,7 @@ export const defaultWranglerConfig: Config = { build: { command: undefined, watch_dir: "./src", cwd: undefined }, no_bundle: undefined, minify: undefined, + keep_names: undefined, dispatch_namespaces: [], first_party_worker: undefined, logfwdr: { bindings: [] }, diff --git a/packages/wrangler/src/config/environment.ts b/packages/wrangler/src/config/environment.ts index 5d87283668c7..4d05bc3db693 100644 --- a/packages/wrangler/src/config/environment.ts +++ b/packages/wrangler/src/config/environment.ts @@ -306,6 +306,14 @@ interface EnvironmentInheritable { */ minify: boolean | undefined; + /** + * Keep function names after javascript transpilations. + * + * @default {true} + * @inheritable + */ + keep_names: boolean | undefined; + /** * Designates this Worker as an internal-only "first-party" Worker. * diff --git a/packages/wrangler/src/config/validation.ts b/packages/wrangler/src/config/validation.ts index 46d0ef504f49..133a6804da1a 100644 --- a/packages/wrangler/src/config/validation.ts +++ b/packages/wrangler/src/config/validation.ts @@ -1417,6 +1417,14 @@ function normalizeAndValidateEnvironment( isBoolean, undefined ), + keep_names: inheritable( + diagnostics, + topLevelEnv, + rawEnv, + "keep_names", + isBoolean, + undefined + ), first_party_worker: inheritable( diagnostics, topLevelEnv, diff --git a/packages/wrangler/src/deploy/deploy.ts b/packages/wrangler/src/deploy/deploy.ts index e1779dbce8c8..d0c94bdeaff2 100644 --- a/packages/wrangler/src/deploy/deploy.ts +++ b/packages/wrangler/src/deploy/deploy.ts @@ -558,6 +558,7 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m jsxFragment, tsconfig: props.tsconfig ?? config.tsconfig, minify, + keepNames: config.keep_names ?? true, sourcemap: uploadSourceMaps, nodejsCompatMode, define: { ...config.define, ...props.defines }, diff --git a/packages/wrangler/src/deployment-bundle/bundle.ts b/packages/wrangler/src/deployment-bundle/bundle.ts index 2658e3a544ef..63c6c0129c16 100644 --- a/packages/wrangler/src/deployment-bundle/bundle.ts +++ b/packages/wrangler/src/deployment-bundle/bundle.ts @@ -120,6 +120,7 @@ export type BundleOptions = { watch: boolean | undefined; tsconfig: string | undefined; minify: boolean | undefined; + keepNames: boolean; nodejsCompatMode: NodeJSCompatMode | undefined; define: Config["define"]; alias: Config["alias"]; @@ -154,6 +155,7 @@ export async function bundleWorker( watch, tsconfig, minify, + keepNames, nodejsCompatMode, alias, define, @@ -353,7 +355,7 @@ export async function bundleWorker( bundle, absWorkingDir: entry.projectRoot, outdir: destination, - keepNames: true, + keepNames, entryNames: entryName || path.parse(entryFile).name, ...(isOutfile ? { diff --git a/packages/wrangler/src/dev/use-esbuild.ts b/packages/wrangler/src/dev/use-esbuild.ts index f8f95aa51a1b..20024c6635b9 100644 --- a/packages/wrangler/src/dev/use-esbuild.ts +++ b/packages/wrangler/src/dev/use-esbuild.ts @@ -42,6 +42,7 @@ export function runBuild( rules, tsconfig, minify, + keepNames, nodejsCompatMode, define, alias, @@ -68,6 +69,7 @@ export function runBuild( alias: Config["alias"]; tsconfig: string | undefined; minify: boolean | undefined; + keepNames: boolean; nodejsCompatMode: NodeJSCompatMode | undefined; noBundle: boolean; findAdditionalModules: boolean | undefined; @@ -148,6 +150,7 @@ export function runBuild( watch: true, tsconfig, minify, + keepNames, nodejsCompatMode, doBindings: durableObjects.bindings, workflowBindings: workflows, diff --git a/packages/wrangler/src/pages/functions/buildPlugin.ts b/packages/wrangler/src/pages/functions/buildPlugin.ts index 293ede51ad30..3778145ec652 100644 --- a/packages/wrangler/src/pages/functions/buildPlugin.ts +++ b/packages/wrangler/src/pages/functions/buildPlugin.ts @@ -17,6 +17,7 @@ export function buildPluginFromFunctions({ routesModule, outdir, minify = false, + keepNames = true, sourcemap = false, watch = false, onEnd = () => {}, @@ -45,6 +46,7 @@ export function buildPluginFromFunctions({ inject: [routesModule], entryName: "index", minify, + keepNames, sourcemap, watch, // We don't currently have a mechanism for Plugins 'requiring' a specific compat date/flag, diff --git a/packages/wrangler/src/pages/functions/buildWorker.ts b/packages/wrangler/src/pages/functions/buildWorker.ts index b897a7628440..04adce259d2b 100644 --- a/packages/wrangler/src/pages/functions/buildWorker.ts +++ b/packages/wrangler/src/pages/functions/buildWorker.ts @@ -23,6 +23,7 @@ export type Options = { outfile?: string; outdir?: string; minify?: boolean; + keepNames?: boolean; sourcemap?: boolean; fallbackService?: string; watch?: boolean; @@ -41,6 +42,7 @@ export function buildWorkerFromFunctions({ outfile = join(getPagesTmpDir(), `./functionsWorker-${Math.random()}.js`), outdir, minify = false, + keepNames = true, sourcemap = false, fallbackService = "ASSETS", watch = false, @@ -72,6 +74,7 @@ export function buildWorkerFromFunctions({ inject: [routesModule], ...(outdir ? { entryName: "index" } : { entryName: undefined }), minify, + keepNames, sourcemap, watch, nodejsCompatMode, @@ -105,6 +108,7 @@ export type RawOptions = { bundle?: boolean; externalModules?: string[]; minify?: boolean; + keepNames?: boolean; sourcemap?: boolean; watch?: boolean; plugins?: Plugin[]; @@ -133,6 +137,7 @@ export function buildRawWorker({ bundle = true, externalModules, minify = false, + keepNames = true, sourcemap = false, watch = false, plugins = [], @@ -160,6 +165,7 @@ export function buildRawWorker({ moduleCollector, additionalModules, minify, + keepNames, sourcemap, watch, nodejsCompatMode, diff --git a/packages/wrangler/src/versions/upload.ts b/packages/wrangler/src/versions/upload.ts index afc47871c4c1..939884de1944 100644 --- a/packages/wrangler/src/versions/upload.ts +++ b/packages/wrangler/src/versions/upload.ts @@ -569,6 +569,7 @@ See https://developers.cloudflare.com/workers/platform/compatibility-dates for m jsxFragment, tsconfig: props.tsconfig ?? config.tsconfig, minify, + keepNames: config.keep_names ?? true, sourcemap: uploadSourceMaps, nodejsCompatMode, define: { ...config.define, ...props.defines },