Skip to content

Commit

Permalink
fix: avoid injecting esbuild watch stubs into production Worker code (#…
Browse files Browse the repository at this point in the history
…5960)

When we added the ability to include additional modules in the deployed bundle of a Worker,
we inadvertently also included some boiler plate code that is only needed at development time.

This fix ensures that this code is only injected if we are running esbuild in watch mode
(e.g. `wrangler dev`) and not when building for deployment.

It is interesting to note that this boilerplate only gets included in the production code
if there is an import of CommonJS code in the Worker, which esbuild needs to convert to an
ESM import.

Fixes [#4269](#4269)
  • Loading branch information
petebacondarwin authored Jun 4, 2024
1 parent 6a4f20d commit e648825
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 7 deletions.
17 changes: 17 additions & 0 deletions .changeset/popular-ravens-add.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
"wrangler": patch
---

fix: avoid injecting esbuild watch stubs into production Worker code

When we added the ability to include additional modules in the deployed bundle of a Worker,
we inadvertently also included some boiler plate code that is only needed at development time.

This fix ensures that this code is only injected if we are running esbuild in watch mode
(e.g. `wrangler dev`) and not when building for deployment.

It is interesting to note that this boilerplate only gets included in the production code
if there is an import of CommonJS code in the Worker, which esbuild needs to convert to an
ESM import.

Fixes [#4269](https://github.com/cloudflare/workers-sdk/issues/4269)
18 changes: 17 additions & 1 deletion packages/wrangler/src/__tests__/deploy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2601,7 +2601,18 @@ addEventListener('fetch', event => {});`
find_additional_modules: true,
rules: [{ type: "ESModule", globs: ["**/*.mjs"] }],
});
writeWorkerSource({ type: "esm" });
// Create a Worker that imports a CommonJS module to trigger esbuild to add
// extra boilerplate to convert to ESM imports.
fs.writeFileSync(`another.cjs`, `module.exports.foo = 100;`);
fs.writeFileSync(
`index.js`,
`import { foo } from "./another.cjs";
export default {
async fetch(request) {
return new Response('Hello' + foo);
},
};`
);
fs.mkdirSync("a/b/c", { recursive: true });
fs.writeFileSync(
"a/1.mjs",
Expand All @@ -2621,6 +2632,11 @@ addEventListener('fetch', event => {});`
);
writeAssets(assets);
mockUploadWorkerRequest({
expectedEntry(entry) {
// Ensure that we have not included the watch stub in production code.
// This is only needed in `wrangler dev`.
expect(entry).not.toMatch(/modules-watch-stub\.js/);
},
expectedBindings: [
{
name: "__STATIC_CONTENT",
Expand Down
6 changes: 4 additions & 2 deletions packages/wrangler/src/__tests__/helpers/mock-upload-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type { HttpResponseResolver } from "msw";
export function mockUploadWorkerRequest(
options: {
available_on_subdomain?: boolean;
expectedEntry?: string | RegExp;
expectedEntry?: string | RegExp | ((entry: string | null) => void);
expectedMainModule?: string;
expectedType?: "esm" | "sw";
expectedBindings?: unknown;
Expand Down Expand Up @@ -47,8 +47,10 @@ export function mockUploadWorkerRequest(
}

const formBody = await request.formData();
if (expectedEntry !== undefined) {
if (typeof expectedEntry === "string" || expectedEntry instanceof RegExp) {
expect(await serialize(formBody.get("index.js"))).toMatch(expectedEntry);
} else if (typeof expectedEntry === "function") {
expectedEntry(await serialize(formBody.get("index.js")));
}
const metadata = JSON.parse(
await toString(formBody.get("metadata"))
Expand Down
10 changes: 6 additions & 4 deletions packages/wrangler/src/deployment-bundle/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,10 +266,12 @@ export async function bundleWorker(
inject.push(...(result.inject ?? []));
}

// `esbuild` doesn't support returning `watch*` options from `onStart()`
// plugin callbacks. Instead, we define an empty virtual module that is
// imported in this injected module. Importing that module registers watchers.
inject.push(path.resolve(getBasePath(), "templates/modules-watch-stub.js"));
if (watch) {
// `esbuild` doesn't support returning `watch*` options from `onStart()`
// plugin callbacks. Instead, we define an empty virtual module that is
// imported in this injected module. Importing that module registers watchers.
inject.push(path.resolve(getBasePath(), "templates/modules-watch-stub.js"));
}

const buildOptions: esbuild.BuildOptions & { metafile: true } = {
// Don't use entryFile here as the file may have been changed when applying the middleware
Expand Down

0 comments on commit e648825

Please sign in to comment.