From 2b5ae26db27ca58ff75eb17e4132987031743460 Mon Sep 17 00:00:00 2001 From: Elliott Johnson Date: Thu, 9 Jul 2026 20:26:30 +0000 Subject: [PATCH] fix: externalize `@opentelemetry/api` to prevent chunk colocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When `instrumentation.server.js` and application code both import `@opentelemetry/api`, the bundler may colocate it into a shared chunk that also contains application modules. The compiled instrumentation entry then imports that chunk — evaluating application modules before `Server.init()` has called `set_env()`. Externalizing `@opentelemetry/api` ensures: - No shared chunks between instrumentation and app code (via this dep) - A single module instance so OTEL hooks registered in instrumentation are visible to the SvelteKit runtime's tracer Added to `ssr.external` in the kit Vite plugin and to adapter-node's external list (since `@opentelemetry/api` is an optional peer dep, not in `pkg.dependencies`, and wouldn't be matched by the existing regex). Closes https://github.com/sveltejs/kit/issues/16288 --- .changeset/externalize-opentelemetry-api.md | 6 ++++++ packages/adapter-node/index.js | 7 ++++++- packages/kit/src/exports/vite/index.js | 13 ++++++++++++- 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 .changeset/externalize-opentelemetry-api.md diff --git a/.changeset/externalize-opentelemetry-api.md b/.changeset/externalize-opentelemetry-api.md new file mode 100644 index 000000000000..2c1f00dc698f --- /dev/null +++ b/.changeset/externalize-opentelemetry-api.md @@ -0,0 +1,6 @@ +--- +'@sveltejs/kit': patch +'@sveltejs/adapter-node': patch +--- + +fix: externalize `@opentelemetry/api` to prevent bundler chunk colocation between `instrumentation.server.js` and application code diff --git a/packages/adapter-node/index.js b/packages/adapter-node/index.js index b0bea8b92a8f..d359b63376d3 100644 --- a/packages/adapter-node/index.js +++ b/packages/adapter-node/index.js @@ -77,7 +77,12 @@ export default function (opts = {}) { input, external: [ // dependencies could have deep exports, so we need a regex - ...Object.keys(pkg.dependencies || {}).map((d) => new RegExp(`^${d}(\\/.*)?$`)) + ...Object.keys(pkg.dependencies || {}).map((d) => new RegExp(`^${d}(\\/.*)?$`)), + // `@opentelemetry/api` is an optional peer dependency of `@sveltejs/kit`, + // so it's not in `pkg.dependencies` and wouldn't be matched by the regex above. + // It must stay external so that `instrumentation.server.js` and the SvelteKit + // runtime share a single instance — see https://github.com/sveltejs/kit/issues/16288 + /^@opentelemetry\/api(\/.*)?$/ ], platform: 'node', resolve: { diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index ea4d1588831d..14c88424ca3e 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -494,7 +494,18 @@ function kit({ svelte_config }) { // These Kit dependencies are packaged as CommonJS, which means they must always be externalized. // Without this, the tests will still pass but `pnpm dev` will fail in projects that link `@sveltejs/kit`. - /** @type {NonNullable} */ (new_config.ssr).external = ['cookie']; + // + // `@opentelemetry/api` must be externalized so that `instrumentation.server.js` and the + // SvelteKit runtime share a single instance of the module (the global tracer/propagation + // is set on that instance — two bundled copies would mean instrumentation hooks are + // invisible to the runtime). Externalizing also prevents the bundler from colocating + // `@opentelemetry/api` into a shared chunk that also contains application modules, which + // would cause those modules to be evaluated before `Server.init()` sets env vars — see + // https://github.com/sveltejs/kit/issues/16288 + /** @type {NonNullable} */ (new_config.ssr).external = [ + 'cookie', + '@opentelemetry/api' + ]; } // Vite's `define` is a compile-time text replacement, but Vitest strips