diff --git a/errors/deprecated-analyticsid.mdx b/errors/deprecated-analyticsid.mdx new file mode 100644 index 0000000000..728de3b579 --- /dev/null +++ b/errors/deprecated-analyticsid.mdx @@ -0,0 +1,20 @@ +--- +title: config.analytics is deprecated +--- + +## Why This Error Occurred + +The Core Web Vitals of your Next.js application could be tracked and sent to any backend of your choice. + +Earlier version of Next.js enable tracking by specifying `analyticsId` into your `next.config.js` file. + +This configuration mechanism will be removed in nextjs@15, as it could be elegantly replaced with `useReportWebVitals` built-in hook. + +## Possible Ways to Fix It + +To remove this warning, you must remove `analyticsId` from your `next.config.js` file. + +To keep tracking your Core Web Vitals, you could: + +- use `useReportWebVitals` hook as explained [here](https://nextjs.org/docs/app/api-reference/functions/use-report-web-vitals) and send the metrics to any backend of your choice. +- [install and use](https://vercel.com/docs/speed-insights/quickstart) `@vercel/speed-insights` package into your application diff --git a/packages/next/src/build/index.ts b/packages/next/src/build/index.ts index 92a5132eac..79be640bcb 100644 --- a/packages/next/src/build/index.ts +++ b/packages/next/src/build/index.ts @@ -9,7 +9,7 @@ import type { Revalidate } from '../server/lib/revalidate' import '../lib/setup-exception-listeners' import { loadEnvConfig, type LoadedEnvFiles } from '@next/env' -import { bold, yellow, green } from '../lib/picocolors' +import { bold, yellow } from '../lib/picocolors' import crypto from 'crypto' import { makeRe } from 'next/dist/compiled/micromatch' import { existsSync, promises as fs } from 'fs' @@ -3090,13 +3090,11 @@ export default async function build( .traceFn(() => printCustomRoutes({ redirects, rewrites, headers })) } + // TODO: remove in the next major version if (config.analyticsId) { - console.log( - bold(green('Next.js Speed Insights')) + - ' is enabled for this production build. ' + - "You'll receive a Real Experience Score computed by all of your visitors." + Log.warn( + `\`config.analyticsId\` is deprecated and will be removed in next major version. Read more: https://nextjs.org/docs/messages/deprecated-analyticsid` ) - console.log('') } if (Boolean(config.experimental.nextScriptWorkers)) { diff --git a/packages/next/src/build/webpack/plugins/define-env-plugin.ts b/packages/next/src/build/webpack/plugins/define-env-plugin.ts index ef6aa0631e..38a753d3ab 100644 --- a/packages/next/src/build/webpack/plugins/define-env-plugin.ts +++ b/packages/next/src/build/webpack/plugins/define-env-plugin.ts @@ -190,7 +190,7 @@ export function getDefineEnv({ 'process.env.__NEXT_CONFIG_OUTPUT': JSON.stringify(config.output), 'process.env.__NEXT_I18N_SUPPORT': JSON.stringify(!!config.i18n), 'process.env.__NEXT_I18N_DOMAINS': JSON.stringify(config.i18n?.domains), - 'process.env.__NEXT_ANALYTICS_ID': JSON.stringify(config.analyticsId), + 'process.env.__NEXT_ANALYTICS_ID': JSON.stringify(config.analyticsId), // TODO: remove in the next major version 'process.env.__NEXT_NO_MIDDLEWARE_URL_NORMALIZE': JSON.stringify( config.skipMiddlewareUrlNormalize ), diff --git a/packages/next/src/cli/next-dev.ts b/packages/next/src/cli/next-dev.ts index aba4e22d49..8517bd04bf 100644 --- a/packages/next/src/cli/next-dev.ts +++ b/packages/next/src/cli/next-dev.ts @@ -209,6 +209,13 @@ const nextDev: CliCommand = async (args) => { traceUploadUrl = args['--experimental-upload-trace'] } + // TODO: remove in the next major version + if (config.analyticsId) { + Log.warn( + `\`config.analyticsId\` is deprecated and will be removed in next major version. Read more: https://nextjs.org/docs/messages/deprecated-analyticsid` + ) + } + const devServerOptions: StartServerOptions = { dir, port, diff --git a/packages/next/src/client/app-index.tsx b/packages/next/src/client/app-index.tsx index 47d31d263a..10514c7e7b 100644 --- a/packages/next/src/client/app-index.tsx +++ b/packages/next/src/client/app-index.tsx @@ -155,6 +155,7 @@ const StrictModeIfEnabled = process.env.__NEXT_STRICT_MODE_APP : React.Fragment function Root({ children }: React.PropsWithChildren<{}>): React.ReactElement { + // TODO: remove in the next major version if (process.env.__NEXT_ANALYTICS_ID) { // eslint-disable-next-line react-hooks/rules-of-hooks React.useEffect(() => { diff --git a/packages/next/src/client/index.tsx b/packages/next/src/client/index.tsx index f8904d1308..b163c29491 100644 --- a/packages/next/src/client/index.tsx +++ b/packages/next/src/client/index.tsx @@ -27,7 +27,7 @@ import { Portal } from './portal' import initHeadManager from './head-manager' import PageLoader from './page-loader' import type { StyleSheetTuple } from './page-loader' -import measureWebVitals from './performance-relayer' +import measureWebVitals from './performance-relayer' // TODO: remove in the next major version import { RouteAnnouncer } from './route-announcer' import { createRouter, makePublicRouterInstance } from './router' import { getProperError } from '../lib/is-error' @@ -604,6 +604,7 @@ function Root({ () => callbacks.forEach((callback) => callback()), [callbacks] ) + // TODO: remove in the next major version // We should ask to measure the Web Vitals after rendering completes so we // don't cause any hydration delay: React.useEffect(() => { diff --git a/packages/next/src/client/performance-relayer-app.ts b/packages/next/src/client/performance-relayer-app.ts index 67fb16b595..9dea54164d 100644 --- a/packages/next/src/client/performance-relayer-app.ts +++ b/packages/next/src/client/performance-relayer-app.ts @@ -1,3 +1,4 @@ +// TODO: remove in the next major version /* global location */ import type { Metric, ReportCallback } from 'next/dist/compiled/web-vitals' diff --git a/packages/next/src/client/performance-relayer.ts b/packages/next/src/client/performance-relayer.ts index 753fd5ab0f..eef5076508 100644 --- a/packages/next/src/client/performance-relayer.ts +++ b/packages/next/src/client/performance-relayer.ts @@ -1,3 +1,4 @@ +// TODO: remove in the next major version /* global location */ import type { Metric, ReportCallback } from 'next/dist/compiled/web-vitals' diff --git a/packages/next/src/server/config-schema.ts b/packages/next/src/server/config-schema.ts index 4f44f041c4..d7f2df93c0 100644 --- a/packages/next/src/server/config-schema.ts +++ b/packages/next/src/server/config-schema.ts @@ -114,7 +114,7 @@ export const configSchema: zod.ZodType = z.lazy(() => canonicalBase: z.string().optional(), }) .optional(), - analyticsId: z.string().optional(), + analyticsId: z.string().optional(), // TODO: remove in the next major version assetPrefix: z.string().optional(), basePath: z.string().optional(), cacheHandler: z.string().min(1).optional(), diff --git a/packages/next/src/server/config-shared.ts b/packages/next/src/server/config-shared.ts index 7378caefcf..89122c7299 100644 --- a/packages/next/src/server/config-shared.ts +++ b/packages/next/src/server/config-shared.ts @@ -552,7 +552,8 @@ export interface NextConfig extends Record { * Vercel provides zero-configuration insights for Next.js projects hosted on Vercel. * * @default '' - * @see [Next.js Speed Insights](https://nextjs.org/analytics) + * @deprecated will be removed in next major version. Read more: https://nextjs.org/docs/messages/deprecated-analyticsid + * @see [how to fix deprecated analyticsId](https://nextjs.org/docs/messages/deprecated-analyticsid) */ analyticsId?: string @@ -776,7 +777,7 @@ export const defaultConfig: NextConfig = { pageExtensions: ['tsx', 'ts', 'jsx', 'js'], poweredByHeader: true, compress: true, - analyticsId: process.env.VERCEL_ANALYTICS_ID || '', + analyticsId: process.env.VERCEL_ANALYTICS_ID || '', // TODO: remove in the next major version images: imageConfigDefault, devIndicators: { buildActivity: true, diff --git a/test/e2e/app-dir/app/vercel-speed-insights.test.ts b/test/e2e/app-dir/app/vercel-speed-insights.test.ts index 60b04cead2..c27fe12087 100644 --- a/test/e2e/app-dir/app/vercel-speed-insights.test.ts +++ b/test/e2e/app-dir/app/vercel-speed-insights.test.ts @@ -38,6 +38,9 @@ describe('vercel speed insights', () => { // Analytics events are only sent in production ;(isDev ? describe.skip : describe)('Vercel analytics', () => { it('should send web vitals to Vercel analytics', async () => { + expect(next.cliOutput).toMatch( + '`config.analyticsId` is deprecated and will be removed in next major version. Read more: https://nextjs.org/docs/messages/deprecated-analyticsid' + ) let eventsCount = 0 let countEvents = false const browser = await next.browser('/client-nested', { diff --git a/test/integration/relay-analytics/test/index.test.js b/test/integration/relay-analytics/test/index.test.js index f4c52088d6..5ac4eef0f3 100644 --- a/test/integration/relay-analytics/test/index.test.js +++ b/test/integration/relay-analytics/test/index.test.js @@ -8,14 +8,15 @@ const appDir = join(__dirname, '../') let appPort let server -let stdout +let stderr jest.setTimeout(1000 * 60 * 2) async function buildApp() { appPort = await findPort() - ;({ stdout } = await nextBuild(appDir, [], { + ;({ stderr } = await nextBuild(appDir, [], { env: { VERCEL_ANALYTICS_ID: 'test' }, stdout: true, + stderr: true, })) server = await nextStart(appDir, appPort) } @@ -107,7 +108,9 @@ function runTest() { expect(isNaN(parseFloat(beacon.value))).toBe(false) } - expect(stdout).toMatch('Next.js Speed Insights') + expect(stderr).toMatch( + '`config.analyticsId` is deprecated and will be removed in next major version. Read more: https://nextjs.org/docs/messages/deprecated-analyticsid' + ) await browser.close() })