mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
fix(next/image): use image-size pkg as additional format detector (#82538)
In a previous PR https://github.com/vercel/next.js/pull/82118 we added a fallback to `sharp().metadata()` when the magic number didn't detect the image format in order to improve detection. But `sharp` can be slow to read metadata, so we should avoid it if we can. So this PR uses the existing `image-size` package to detect the content type in JS and only then does it fallback to the native `sharp` code if necessary. No tests were added since this doesn't change the behavior, only performance.
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -4,6 +4,7 @@ import type { IncomingMessage, ServerResponse } from 'http'
|
||||
import { mediaType } from 'next/dist/compiled/@hapi/accept'
|
||||
import contentDisposition from 'next/dist/compiled/content-disposition'
|
||||
import imageSizeOf from 'next/dist/compiled/image-size'
|
||||
import { detector } from 'next/dist/compiled/image-detector/detector.js'
|
||||
import isAnimated from 'next/dist/compiled/is-animated'
|
||||
import { join } from 'path'
|
||||
import nodeUrl, { type UrlWithParsedQuery } from 'url'
|
||||
@@ -232,11 +233,21 @@ export async function detectContentType(
|
||||
return JP2
|
||||
}
|
||||
|
||||
const sharp = getSharp(null)
|
||||
const meta = await sharp(buffer)
|
||||
.metadata()
|
||||
.catch((_) => null)
|
||||
switch (meta?.format) {
|
||||
let format:
|
||||
| import('sharp').Metadata['format']
|
||||
| ReturnType<typeof detector>
|
||||
| undefined
|
||||
format = detector(buffer)
|
||||
|
||||
if (!format) {
|
||||
const sharp = getSharp(null)
|
||||
const meta = await sharp(buffer)
|
||||
.metadata()
|
||||
.catch((_) => null)
|
||||
format = meta?.format
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
case 'avif':
|
||||
return AVIF
|
||||
case 'webp':
|
||||
@@ -251,6 +262,7 @@ export async function detectContentType(
|
||||
case 'svg':
|
||||
return SVG
|
||||
case 'jxl':
|
||||
case 'jxl-stream':
|
||||
return JXL
|
||||
case 'jp2':
|
||||
return JP2
|
||||
@@ -259,6 +271,12 @@ export async function detectContentType(
|
||||
return TIFF
|
||||
case 'pdf':
|
||||
return PDF
|
||||
case 'bmp':
|
||||
return BMP
|
||||
case 'ico':
|
||||
return ICO
|
||||
case 'icns':
|
||||
return ICNS
|
||||
case 'dcraw':
|
||||
case 'dz':
|
||||
case 'exr':
|
||||
@@ -271,6 +289,13 @@ export async function detectContentType(
|
||||
case 'rad':
|
||||
case 'raw':
|
||||
case 'v':
|
||||
case 'cur':
|
||||
case 'dds':
|
||||
case 'j2c':
|
||||
case 'ktx':
|
||||
case 'pnm':
|
||||
case 'psd':
|
||||
case 'tga':
|
||||
case undefined:
|
||||
default:
|
||||
return null
|
||||
|
||||
@@ -660,6 +660,17 @@ export async function ncc_image_size(task, opts) {
|
||||
.target('src/compiled/image-size')
|
||||
}
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
externals['image-detector'] = 'next/dist/compiled/image-detector'
|
||||
export async function ncc_image_detector(task, opts) {
|
||||
// NOTE: remove this special compile step if the upstream PR lands
|
||||
// https://github.com/image-size/image-size/pull/451
|
||||
await task
|
||||
.source(relative(__dirname, require.resolve('image-size/dist/detector.js')))
|
||||
.ncc({ packageName: 'image-size', externals })
|
||||
.target('src/compiled/image-detector')
|
||||
}
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
externals['@hapi/accept'] = 'next/dist/compiled/@hapi/accept'
|
||||
export async function ncc_hapi_accept(task, opts) {
|
||||
@@ -2281,6 +2292,7 @@ export async function ncc(task, opts) {
|
||||
'ncc_p_queue',
|
||||
'ncc_raw_body',
|
||||
'ncc_image_size',
|
||||
'ncc_image_detector',
|
||||
'ncc_hapi_accept',
|
||||
'ncc_commander',
|
||||
'ncc_node_anser',
|
||||
|
||||
+27
@@ -464,6 +464,33 @@ declare module 'next/dist/compiled/image-size' {
|
||||
export = m
|
||||
}
|
||||
|
||||
declare module 'next/dist/compiled/image-detector/detector.js' {
|
||||
export function detector(
|
||||
arr: Uint8Array
|
||||
):
|
||||
| 'bmp'
|
||||
| 'cur'
|
||||
| 'dds'
|
||||
| 'gif'
|
||||
| 'heif'
|
||||
| 'icns'
|
||||
| 'ico'
|
||||
| 'j2c'
|
||||
| 'jp2'
|
||||
| 'jpg'
|
||||
| 'jxl'
|
||||
| 'jxl-stream'
|
||||
| 'ktx'
|
||||
| 'png'
|
||||
| 'pnm'
|
||||
| 'psd'
|
||||
| 'svg'
|
||||
| 'tga'
|
||||
| 'tiff'
|
||||
| 'webp'
|
||||
| undefined
|
||||
}
|
||||
|
||||
declare module 'next/dist/compiled/@hapi/accept' {
|
||||
import m from '@hapi/accept'
|
||||
export = m
|
||||
|
||||
Reference in New Issue
Block a user