Skip to content

Commit 656a444

Browse files
authored
Remove es-module-lexer (#7073)
1 parent 3235b40 commit 656a444

18 files changed

+66
-39
lines changed

.changeset/tasty-elephants-develop.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"wrangler": patch
3+
---
4+
5+
Internal refactor to remove `es-module-lexer` and support `wrangler types` for Workers with Durable Objects & JSX

packages/wrangler/package.json

-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@
130130
"concurrently": "^8.2.2",
131131
"devtools-protocol": "^0.0.1182435",
132132
"dotenv": "^16.0.0",
133-
"es-module-lexer": "^1.3.0",
134133
"execa": "^6.1.0",
135134
"express": "^4.18.1",
136135
"find-up": "^6.3.0",

packages/wrangler/src/__tests__/api/startDevWorker/BundleController.test.ts

+8
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ describe("BundleController", () => {
7979
define: {},
8080
format: "modules",
8181
moduleRoot: path.resolve("src"),
82+
exports: [],
8283
},
8384
};
8485

@@ -151,6 +152,7 @@ describe("BundleController", () => {
151152
define: {},
152153
format: "modules",
153154
moduleRoot: path.resolve("src"),
155+
exports: [],
154156
},
155157
};
156158

@@ -219,6 +221,7 @@ describe("BundleController", () => {
219221
define: {},
220222
format: "modules",
221223
moduleRoot: path.resolve("."),
224+
exports: [],
222225
},
223226
};
224227

@@ -295,6 +298,7 @@ describe("BundleController", () => {
295298
define: {},
296299
format: "modules",
297300
moduleRoot: path.resolve("src"),
301+
exports: [],
298302
},
299303
});
300304

@@ -353,6 +357,7 @@ describe("BundleController", () => {
353357
define: {},
354358
format: "modules",
355359
moduleRoot: path.resolve("src"),
360+
exports: [],
356361
},
357362
};
358363

@@ -400,6 +405,7 @@ describe("BundleController", () => {
400405
define: {},
401406
format: "modules",
402407
moduleRoot: process.cwd(),
408+
exports: [],
403409
},
404410
legacy: {},
405411
};
@@ -473,6 +479,7 @@ describe("BundleController", () => {
473479
define: {},
474480
format: "modules",
475481
moduleRoot: process.cwd(),
482+
exports: [],
476483
},
477484
};
478485

@@ -518,6 +525,7 @@ describe("BundleController", () => {
518525
define: {},
519526
format: "modules",
520527
moduleRoot: path.resolve("src"),
528+
exports: [],
521529
},
522530
};
523531

packages/wrangler/src/__tests__/api/startDevWorker/LocalRuntimeController.test.ts

+3
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ function makeEsbuildBundle(testBundle: TestBundle): Bundle {
9292
format: "modules",
9393
moduleRoot: "/virtual",
9494
name: undefined,
95+
exports: [],
9596
},
9697
dependencies: {},
9798
sourceMapPath: undefined,
@@ -235,6 +236,7 @@ describe("LocalRuntimeController", () => {
235236
format: "modules",
236237
moduleRoot: "/virtual",
237238
name: undefined,
239+
exports: [],
238240
},
239241
dependencies: {},
240242
sourceMapPath: undefined,
@@ -348,6 +350,7 @@ describe("LocalRuntimeController", () => {
348350
format: "service-worker",
349351
moduleRoot: "/virtual",
350352
name: undefined,
353+
exports: [],
351354
},
352355
dependencies: {},
353356
sourceMapPath: undefined,

packages/wrangler/src/__tests__/find-additional-modules.test.ts

+7
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ describe("traverse module graph", () => {
4242
directory: process.cwd(),
4343
format: "modules",
4444
moduleRoot: process.cwd(),
45+
exports: [],
4546
},
4647
[]
4748
);
@@ -77,6 +78,7 @@ describe("traverse module graph", () => {
7778
directory: process.cwd(),
7879
format: "modules",
7980
moduleRoot: process.cwd(),
81+
exports: [],
8082
},
8183
[{ type: type as ConfigModuleRuleType, globs: ["**/*.js"] }]
8284
);
@@ -111,6 +113,7 @@ describe("traverse module graph", () => {
111113
format: "modules",
112114
// The default module root is dirname(file)
113115
moduleRoot: path.join(process.cwd(), "./src/nested"),
116+
exports: [],
114117
},
115118
[{ type: "ESModule", globs: ["**/*.js"] }]
116119
);
@@ -145,6 +148,7 @@ describe("traverse module graph", () => {
145148
format: "modules",
146149
// The default module root is dirname(file)
147150
moduleRoot: path.join(process.cwd(), "./src"),
151+
exports: [],
148152
},
149153
[{ type: "ESModule", globs: ["**/*.js"] }]
150154
);
@@ -179,6 +183,7 @@ describe("traverse module graph", () => {
179183
format: "modules",
180184
// The default module root is dirname(file)
181185
moduleRoot: path.join(process.cwd(), "./src"),
186+
exports: [],
182187
},
183188
[{ type: "ESModule", globs: ["**/*.mjs"] }]
184189
);
@@ -213,6 +218,7 @@ describe("traverse module graph", () => {
213218
format: "modules",
214219
// The default module root is dirname(file)
215220
moduleRoot: path.join(process.cwd(), "./src"),
221+
exports: [],
216222
},
217223
[]
218224
);
@@ -247,6 +253,7 @@ describe("traverse module graph", () => {
247253
format: "modules",
248254
// The default module root is dirname(file)
249255
moduleRoot: path.join(process.cwd(), "./src"),
256+
exports: [],
250257
},
251258
[
252259
{ type: "Text", globs: ["**/*.txt"] },

packages/wrangler/src/__tests__/guess-worker-format.test.ts

+21-6
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ describe("guess worker format", () => {
1616
process.cwd(),
1717
undefined
1818
);
19-
expect(guess).toBe("modules");
19+
expect(guess.format).toBe("modules");
2020
});
2121

2222
it('should detect a "service-worker" worker', async () => {
@@ -29,7 +29,7 @@ describe("guess worker format", () => {
2929
process.cwd(),
3030
undefined
3131
);
32-
expect(guess).toBe("service-worker");
32+
expect(guess.format).toBe("service-worker");
3333
});
3434

3535
it('should detect a "service-worker" worker using `typeof module`', async () => {
@@ -39,7 +39,7 @@ describe("guess worker format", () => {
3939
process.cwd(),
4040
undefined
4141
);
42-
expect(guess).toBe("service-worker");
42+
expect(guess.format).toBe("service-worker");
4343
});
4444

4545
it('should detect a "service-worker" worker using imports', async () => {
@@ -64,7 +64,7 @@ describe("guess worker format", () => {
6464
process.cwd(),
6565
undefined
6666
);
67-
expect(guess).toBe("service-worker");
67+
expect(guess.format).toBe("service-worker");
6868
});
6969

7070
it("should throw an error when the hint doesn't match the guess (modules - service-worker)", async () => {
@@ -100,7 +100,7 @@ describe("guess worker format", () => {
100100
process.cwd(),
101101
undefined
102102
);
103-
expect(guess).toBe("service-worker");
103+
expect(guess.format).toBe("service-worker");
104104
});
105105

106106
it("logs a warning when a worker has exports, but not a default one", async () => {
@@ -110,11 +110,26 @@ describe("guess worker format", () => {
110110
process.cwd(),
111111
undefined
112112
);
113-
expect(guess).toBe("service-worker");
113+
expect(guess.format).toBe("service-worker");
114114
expect(std.warn).toMatchInlineSnapshot(`
115115
"▲ [WARNING] The entrypoint index.ts has exports like an ES Module, but hasn't defined a default export like a module worker normally would. Building the worker using \\"service-worker\\" format...
116116
117117
"
118118
`);
119119
});
120+
121+
it("should list exports", async () => {
122+
await writeFile(
123+
"./index.ts",
124+
"export default {}; export const Hello ='world'"
125+
);
126+
// Note that this isn't actually a valid worker, because it's missing
127+
// a fetch handler. Regardless, our heuristic is simply to check for exports.
128+
const guess = await guessWorkerFormat(
129+
path.join(process.cwd(), "./index.ts"),
130+
process.cwd(),
131+
undefined
132+
);
133+
expect(guess.exports).toStrictEqual(["Hello", "default"]);
134+
});
120135
});

packages/wrangler/src/__tests__/navigator-user-agent.test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ describe("defineNavigatorUserAgent is respected", () => {
107107
directory: process.cwd(),
108108
format: "modules",
109109
moduleRoot: path.dirname(path.resolve("src/index.js")),
110+
exports: [],
110111
},
111112
path.resolve("dist"),
112113
{
@@ -168,6 +169,7 @@ describe("defineNavigatorUserAgent is respected", () => {
168169
directory: process.cwd(),
169170
format: "modules",
170171
moduleRoot: path.dirname(path.resolve("src/index.js")),
172+
exports: [],
171173
},
172174
path.resolve("dist"),
173175
{

packages/wrangler/src/api/startDevWorker/BundlerController.ts

+2
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ export class BundlerController extends Controller<BundlerControllerEventMap> {
7777
directory: config.directory,
7878
format: config.build.format,
7979
moduleRoot: config.build.moduleRoot,
80+
exports: config.build.exports,
8081
};
8182

8283
const entryDirectory = path.dirname(config.entrypoint);
@@ -214,6 +215,7 @@ export class BundlerController extends Controller<BundlerControllerEventMap> {
214215
directory: config.directory,
215216
format: config.build.format,
216217
moduleRoot: config.build.moduleRoot,
218+
exports: config.build.exports,
217219
};
218220
const { bindings } = await convertBindingsToCfWorkerInitBindings(
219221
config.bindings

packages/wrangler/src/api/startDevWorker/ConfigController.ts

+1
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ async function resolveConfig(
284284
jsxFactory: input.build?.jsxFactory || config.jsx_factory,
285285
jsxFragment: input.build?.jsxFragment || config.jsx_fragment,
286286
tsconfig: input.build?.tsconfig ?? config.tsconfig,
287+
exports: entry.exports,
287288
},
288289
dev: await resolveDevConfig(config, input),
289290
legacy: {

packages/wrangler/src/api/startDevWorker/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ export type StartDevWorkerOptions = Omit<StartDevWorkerInput, "assets"> & {
179179
moduleRules: Rule[];
180180
define: Record<string, string>;
181181
additionalModules: CfModule[];
182+
exports: string[];
182183

183184
processEntrypoint: boolean;
184185
};

packages/wrangler/src/deployment-bundle/entry.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ export type Entry = {
3131
* A worker's name
3232
*/
3333
name?: string | undefined;
34+
35+
/** Export from a Worker's entrypoint */
36+
exports: string[];
3437
};
3538

3639
/**
@@ -78,7 +81,7 @@ export async function getEntry(
7881
}
7982
await runCustomBuild(paths.absolutePath, paths.relativePath, config.build);
8083

81-
const format = await guessWorkerFormat(
84+
const { format, exports } = await guessWorkerFormat(
8285
paths.absolutePath,
8386
directory,
8487
args.format ?? config.build?.upload?.format,
@@ -119,6 +122,7 @@ export async function getEntry(
119122
moduleRoot:
120123
args.moduleRoot ?? config.base_dir ?? path.dirname(paths.absolutePath),
121124
name: config.name ?? "worker",
125+
exports,
122126
};
123127
}
124128

packages/wrangler/src/deployment-bundle/guess-worker-format.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export default async function guessWorkerFormat(
1919
entryWorkingDirectory: string,
2020
hint: CfScriptFormat | undefined,
2121
tsconfig?: string | undefined
22-
): Promise<CfScriptFormat> {
22+
): Promise<{ format: CfScriptFormat; exports: string[] }> {
2323
const parsedEntryPath = path.parse(entryFile);
2424
if (parsedEntryPath.ext == ".py") {
2525
logger.warn(
@@ -28,7 +28,7 @@ export default async function guessWorkerFormat(
2828
entryFile
2929
)} defines a Python worker, support for Python workers is currently experimental. Python workers with a requirements.txt file can only be run locally and cannot be deployed.`
3030
);
31-
return "modules";
31+
return { format: "modules", exports: [] };
3232
}
3333

3434
const result = await esbuild.build({
@@ -77,5 +77,5 @@ export default async function guessWorkerFormat(
7777
}
7878
}
7979
}
80-
return guessedWorkerFormat;
80+
return { format: guessedWorkerFormat, exports };
8181
}

packages/wrangler/src/dev/dev.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ function DevSession(props: DevSessionProps) {
372372
nodejsCompatMode: props.nodejsCompatMode ?? null,
373373
format: props.entry.format,
374374
moduleRoot: props.entry.moduleRoot,
375+
exports: props.entry.exports,
375376
},
376377
dev: {
377378
auth: async () => {

packages/wrangler/src/dev/miniflare.ts

+1-12
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import assert from "node:assert";
22
import { randomUUID } from "node:crypto";
33
import path from "node:path";
4-
import * as esmLexer from "es-module-lexer";
54
import {
65
CoreHeaders,
76
HttpOptions_Style,
@@ -259,14 +258,6 @@ export function buildLog(): Log {
259258
return new WranglerLog(level, { prefix: "wrangler-UserWorker" });
260259
}
261260

262-
async function getEntrypointNames(entrypointSource: string) {
263-
await esmLexer.init;
264-
const [_imports, exports] = esmLexer.parse(entrypointSource);
265-
// TODO(soon): support `export * from "...";` with `--no-bundle`. Without
266-
// `--no-bundle`, `esbuild` will bundle these, so they'll be picked up here.
267-
return exports.map(({ n }) => n);
268-
}
269-
270261
async function buildSourceOptions(
271262
config: Omit<ConfigBundle, "rules">
272263
): Promise<{ sourceOptions: SourceOptions; entrypointNames: string[] }> {
@@ -285,9 +276,7 @@ async function buildSourceOptions(
285276
config.bundle.modules
286277
);
287278

288-
const entrypointNames = isPython
289-
? []
290-
: await getEntrypointNames(entrypointSource);
279+
const entrypointNames = isPython ? [] : config.bundle.entry.exports;
291280

292281
const modulesRoot = path.dirname(scriptPath);
293282
const sourceOptions: SourceOptions = {

packages/wrangler/src/pages/functions/buildPlugin.ts

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export function buildPluginFromFunctions({
3131
directory: functionsDirectory,
3232
format: "modules",
3333
moduleRoot: functionsDirectory,
34+
exports: [],
3435
};
3536
const moduleCollector = createModuleCollector({
3637
entry,

0 commit comments

Comments
 (0)