Skip to content

Commit 67acb2f

Browse files
authored
fix build issues with @opentelemetry (#302)
1 parent deaf845 commit 67acb2f

File tree

7 files changed

+329
-42
lines changed

7 files changed

+329
-42
lines changed

.changeset/selfish-pumpkins-sin.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@opennextjs/cloudflare": patch
3+
---
4+
5+
fix build issues with `@opentelemetry`
6+
7+
By using the pre-compiled library provided by Next.

packages/cloudflare/src/cli/build/bundle-server.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { build, Plugin } from "esbuild";
1111
import { patchOptionalDependencies } from "./patches/ast/optional-deps.js";
1212
import { patchVercelOgLibrary } from "./patches/ast/patch-vercel-og-library.js";
1313
import * as patches from "./patches/index.js";
14+
import fixRequire from "./patches/plugins/require.js";
1415
import inlineRequirePagePlugin from "./patches/plugins/require-page.js";
1516
import setWranglerExternal from "./patches/plugins/wrangler-external.js";
1617
import { normalizePath, patchCodeWithValidations } from "./utils/index.js";
@@ -49,7 +50,6 @@ export async function bundleServer(buildOpts: BuildOptions): Promise<void> {
4950

5051
console.log(`\x1b[35m⚙️ Bundling the OpenNext server...\n\x1b[0m`);
5152

52-
patches.patchWranglerDeps(buildOpts);
5353
await patches.updateWebpackChunksFile(buildOpts);
5454
patchVercelOgLibrary(buildOpts);
5555

@@ -70,6 +70,7 @@ export async function bundleServer(buildOpts: BuildOptions): Promise<void> {
7070
createFixRequiresESBuildPlugin(buildOpts),
7171
inlineRequirePagePlugin(buildOpts),
7272
setWranglerExternal(),
73+
fixRequire(),
7374
],
7475
external: ["./middleware/handler.mjs", ...optionalDependencies],
7576
alias: {
@@ -102,7 +103,6 @@ export async function bundleServer(buildOpts: BuildOptions): Promise<void> {
102103
"process.env.NODE_ENV": '"production"',
103104
"process.env.NEXT_MINIMAL": "true",
104105
},
105-
// We need to set platform to node so that esbuild doesn't complain about the node imports
106106
platform: "node",
107107
banner: {
108108
js: `
@@ -168,7 +168,10 @@ globalThis.__BUILD_TIMESTAMP_MS__ = ${Date.now()};
168168
/**
169169
* This function applies patches required for the code to run on workers.
170170
*/
171-
async function updateWorkerBundledCode(workerOutputFile: string, buildOpts: BuildOptions): Promise<void> {
171+
export async function updateWorkerBundledCode(
172+
workerOutputFile: string,
173+
buildOpts: BuildOptions
174+
): Promise<void> {
172175
const code = await readFile(workerOutputFile, "utf8");
173176

174177
const patchedCode = await patchCodeWithValidations(code, [
@@ -191,11 +194,6 @@ async function updateWorkerBundledCode(workerOutputFile: string, buildOpts: Buil
191194
// TODO: implement for cf (possibly in @opennextjs/aws)
192195
.replace("patchAsyncStorage();", "//patchAsyncStorage();"),
193196
],
194-
[
195-
'`eval("require")` calls',
196-
(code) => code.replaceAll('eval("require")', "require"),
197-
{ isOptional: true },
198-
],
199197
[
200198
"`require.resolve` call",
201199
// workers do not support dynamic require nor require.resolve
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import fs from "node:fs/promises";
2+
3+
import type { PluginBuild } from "esbuild";
4+
5+
export default function fixRequire() {
6+
return {
7+
name: "fix-require",
8+
9+
setup: async (build: PluginBuild) => {
10+
build.onLoad({ filter: /.*/ }, async ({ path }) => {
11+
let contents = await fs.readFile(path, "utf-8");
12+
13+
// `eval(...)` is not supported by workerd.
14+
contents = contents.replaceAll(`eval("require")`, "require");
15+
16+
// `@opentelemetry` has a few issues.
17+
//
18+
// Next.js has the following code in `next/dist/server/lib/trace/tracer.js`:
19+
//
20+
// try {
21+
// api = require('@opentelemetry/api');
22+
// } catch (err) {
23+
// api = require('next/dist/compiled/@opentelemetry/api');
24+
// }
25+
//
26+
// The intent is to allow users to install their own version of `@opentelemetry/api`.
27+
//
28+
// The problem is that even when users do not explicitely install `@opentelemetry/api`,
29+
// `require('@opentelemetry/api')` resolves to the package which is a dependency
30+
// of Next.
31+
//
32+
// The second problem is that when Next traces files, it would not copy the `api/build/esm`
33+
// folder (used by the `module` conditions in package.json) it would only copy `api/build/src`.
34+
// This could be solved by updating the next config:
35+
//
36+
// const nextConfig: NextConfig = {
37+
// // ...
38+
// outputFileTracingIncludes: {
39+
// "*": ["./node_modules/@opentelemetry/api/build/**/*"],
40+
// },
41+
// };
42+
//
43+
// We can consider doing that when we want to enable users to install their own version
44+
// of `@opentelemetry/api`. For now we simply use the pre-compiled version.
45+
contents = contents.replace(
46+
/require\(.@opentelemetry\/api.\)/g,
47+
`require("next/dist/compiled/@opentelemetry/api")`
48+
);
49+
50+
return { contents };
51+
});
52+
},
53+
};
54+
}

packages/cloudflare/src/cli/build/patches/to-investigate/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,3 @@ export * from "./patch-exception-bubbling.js";
44
export * from "./patch-find-dir.js";
55
export * from "./patch-load-instrumentation-module.js";
66
export * from "./patch-read-file.js";
7-
export * from "./wrangler-deps.js";

packages/cloudflare/src/cli/build/patches/to-investigate/wrangler-deps.ts

Lines changed: 0 additions & 29 deletions
This file was deleted.

0 commit comments

Comments
 (0)