rsnext/packages/next/telemetry/events/version.ts
Steven e28d03c5a4
Add experimental next/future/image component (#37927)
This PR introduces a new experimental component, `next/future/image`, which is inspired by the existing experimental `layout="raw"`.

The difference is that much of the code has been deleted in order to reduce client-side code as well as reduce complexity:

- No `layout` prop
- No `loader` config (although `loader` prop works)
- No `IntersectionObserver`, use native `loading="lazy"` 
  - No `lazyBoundary`
  - No `lazyRoot`
- No `fill` (yet) so width & height are required
- No `objectFit` (use `style` instead)
- No `objectPosition` (use `style` instead)

This improves performance because native `loading="lazy"` doesn't need to wait for React Hydration and client-side JS.

In a future PR, we will modify `next/image` to remove `layout="raw"` since this new component supersedes it.

## Feature

- [x] Integration tests added
- [x] Documentation added
- [x] Telemetry added. In case of a feature if it's used or not.
- [x] Errors have helpful link attached, see `contributing.md`
2022-06-24 14:56:05 +00:00

116 lines
3.6 KiB
TypeScript

import path from 'path'
import { NextConfigComplete } from '../../server/config-shared'
const EVENT_VERSION = 'NEXT_CLI_SESSION_STARTED'
type EventCliSessionStarted = {
nextVersion: string
nodeVersion: string
cliCommand: string
isSrcDir: boolean | null
hasNowJson: boolean
isCustomServer: boolean | null
hasNextConfig: boolean
buildTarget: string
hasWebpackConfig: boolean
hasBabelConfig: boolean
basePathEnabled: boolean
i18nEnabled: boolean
imageEnabled: boolean
imageFutureEnabled: boolean
locales: string | null
localeDomainsCount: number | null
localeDetectionEnabled: boolean | null
imageDomainsCount: number | null
imageRemotePatternsCount: number | null
imageSizes: string | null
imageLoader: string | null
imageFormats: string | null
trailingSlashEnabled: boolean
reactStrictMode: boolean
webpackVersion: number | null
}
function hasBabelConfig(dir: string): boolean {
try {
const noopFile = path.join(dir, 'noop.js')
const res = require('next/dist/compiled/babel/core').loadPartialConfig({
cwd: dir,
filename: noopFile,
sourceFileName: noopFile,
}) as any
const isForTooling =
res.options?.presets?.every(
(e: any) => e?.file?.request === 'next/babel'
) && res.options?.plugins?.length === 0
return res.hasFilesystemConfig() && !isForTooling
} catch {
return false
}
}
export function eventCliSession(
dir: string,
nextConfig: NextConfigComplete,
event: Omit<
EventCliSessionStarted,
| 'nextVersion'
| 'nodeVersion'
| 'hasNextConfig'
| 'buildTarget'
| 'hasWebpackConfig'
| 'hasBabelConfig'
| 'basePathEnabled'
| 'i18nEnabled'
| 'imageEnabled'
| 'imageFutureEnabled'
| 'locales'
| 'localeDomainsCount'
| 'localeDetectionEnabled'
| 'imageDomainsCount'
| 'imageRemotePatternsCount'
| 'imageSizes'
| 'imageLoader'
| 'imageFormats'
| 'trailingSlashEnabled'
| 'reactStrictMode'
>
): { eventName: string; payload: EventCliSessionStarted }[] {
// This should be an invariant, if it fails our build tooling is broken.
if (typeof process.env.__NEXT_VERSION !== 'string') {
return []
}
const { images, i18n, experimental } = nextConfig || {}
const payload: EventCliSessionStarted = {
nextVersion: process.env.__NEXT_VERSION,
nodeVersion: process.version,
cliCommand: event.cliCommand,
isSrcDir: event.isSrcDir,
hasNowJson: event.hasNowJson,
isCustomServer: event.isCustomServer,
hasNextConfig: nextConfig.configOrigin !== 'default',
buildTarget: nextConfig.target === 'server' ? 'default' : nextConfig.target,
hasWebpackConfig: typeof nextConfig?.webpack === 'function',
hasBabelConfig: hasBabelConfig(dir),
imageEnabled: !!images,
imageFutureEnabled: !!experimental.images?.allowFutureImage,
basePathEnabled: !!nextConfig?.basePath,
i18nEnabled: !!i18n,
locales: i18n?.locales ? i18n.locales.join(',') : null,
localeDomainsCount: i18n?.domains ? i18n.domains.length : null,
localeDetectionEnabled: !i18n ? null : i18n.localeDetection !== false,
imageDomainsCount: images?.domains ? images.domains.length : null,
imageRemotePatternsCount: experimental?.images?.remotePatterns
? experimental.images.remotePatterns.length
: null,
imageSizes: images?.imageSizes ? images.imageSizes.join(',') : null,
imageLoader: images?.loader,
imageFormats: images?.formats ? images.formats.join(',') : null,
trailingSlashEnabled: !!nextConfig?.trailingSlash,
reactStrictMode: !!nextConfig?.reactStrictMode,
webpackVersion: event.webpackVersion || null,
}
return [{ eventName: EVENT_VERSION, payload }]
}