From 5eafa401c076796fba7663dad9ca254ab6f1972f Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Fri, 28 Jun 2024 11:49:14 +0200 Subject: [PATCH] fix(nextjs): Attempt to ignore critical dependency warnings (#12694) --- packages/nextjs/src/config/types.ts | 18 +++++++++++++++++- packages/nextjs/src/config/webpack.ts | 26 ++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/packages/nextjs/src/config/types.ts b/packages/nextjs/src/config/types.ts index b84c55e5611f..883ba3c26d41 100644 --- a/packages/nextjs/src/config/types.ts +++ b/packages/nextjs/src/config/types.ts @@ -404,6 +404,22 @@ export type NextConfigFunction = ( * Webpack config */ +// Note: The interface for `ignoreWarnings` is larger but we only need this. See https://webpack.js.org/configuration/other-options/#ignorewarnings +export type IgnoreWarningsOption = ( + | { module?: RegExp; message?: RegExp } + | (( + webpackError: { + module?: { + readableIdentifier: (requestShortener: unknown) => string; + }; + message: string; + }, + compilation: { + requestShortener: unknown; + }, + ) => boolean) +)[]; + // The two possible formats for providing custom webpack config in `next.config.js` export type WebpackConfigFunction = (config: WebpackConfigObject, options: BuildContext) => WebpackConfigObject; export type WebpackConfigObject = { @@ -413,7 +429,7 @@ export type WebpackConfigObject = { output: { filename: string; path: string }; target: string; context: string; - ignoreWarnings?: { module?: RegExp }[]; // Note: The interface for `ignoreWarnings` is larger but we only need this. See https://webpack.js.org/configuration/other-options/#ignorewarnings + ignoreWarnings?: IgnoreWarningsOption; resolve?: { modules?: string[]; alias?: { [key: string]: string | boolean }; diff --git a/packages/nextjs/src/config/webpack.ts b/packages/nextjs/src/config/webpack.ts index eece7ff30305..4002db18f295 100644 --- a/packages/nextjs/src/config/webpack.ts +++ b/packages/nextjs/src/config/webpack.ts @@ -14,6 +14,7 @@ import type { VercelCronsConfig } from '../common/types'; import type { BuildContext, EntryPropertyObject, + IgnoreWarningsOption, NextConfigObject, SentryBuildOptions, WebpackConfigFunction, @@ -72,9 +73,7 @@ export function constructWebpackConfigFunction( // Add a loader which will inject code that sets global values addValueInjectionLoader(newConfig, userNextConfig, userSentryOptions, buildContext); - if (isServer) { - addOtelWarningIgnoreRule(newConfig); - } + addOtelWarningIgnoreRule(newConfig); let pagesDirPath: string | undefined; const maybePagesDirPath = path.join(projectDir, 'pages'); @@ -668,9 +667,28 @@ function getRequestAsyncStorageModuleLocation( function addOtelWarningIgnoreRule(newConfig: WebpackConfigObjectWithModuleRules): void { const ignoreRules = [ + // Inspired by @matmannion: https://github.com/getsentry/sentry-javascript/issues/12077#issuecomment-2180307072 + (warning, compilation) => { + // This is wapped in try-catch because we are vendoring types for this hook and we can't be 100% sure that we are accessing API that is there + try { + if (!warning.module) { + return false; + } + + const isDependencyThatMayRaiseCriticalDependencyMessage = + /@opentelemetry\/instrumentation/.test(warning.module.readableIdentifier(compilation.requestShortener)) || + /@prisma\/instrumentation/.test(warning.module.readableIdentifier(compilation.requestShortener)); + const isCriticalDependencyMessage = /Critical dependency/.test(warning.message); + + return isDependencyThatMayRaiseCriticalDependencyMessage && isCriticalDependencyMessage; + } catch { + return false; + } + }, + // We provide these objects in addition to the hook above to provide redundancy in case the hook fails. { module: /@opentelemetry\/instrumentation/, message: /Critical dependency/ }, { module: /@prisma\/instrumentation/, message: /Critical dependency/ }, - ]; + ] satisfies IgnoreWarningsOption; if (newConfig.ignoreWarnings === undefined) { newConfig.ignoreWarnings = ignoreRules;