Skip to content

Commit

Permalink
Add performance tracing for next-image-loader (#27043)
Browse files Browse the repository at this point in the history
  • Loading branch information
timneutkens authored Jul 9, 2021
1 parent 9f1d5d7 commit 7c56684
Showing 1 changed file with 54 additions and 43 deletions.
97 changes: 54 additions & 43 deletions packages/next/build/webpack/loaders/next-image-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,52 +6,63 @@ const BLUR_IMG_SIZE = 8
const BLUR_QUALITY = 70
const VALID_BLUR_EXT = ['jpeg', 'png', 'webp']

async function nextImageLoader(content) {
const isServer = loaderUtils.getOptions(this).isServer
const context = this.rootContext
const opts = { context, content }
const interpolatedName = loaderUtils.interpolateName(
this,
'/static/image/[path][name].[hash].[ext]',
opts
)

let extension = loaderUtils.interpolateName(this, '[ext]', opts)
if (extension === 'jpg') {
extension = 'jpeg'
}

const imageSize = sizeOf(content)
let blurDataURL
if (VALID_BLUR_EXT.includes(extension)) {
// Shrink the image's largest dimension
const resizeOperationOpts =
imageSize.width >= imageSize.height
? { type: 'resize', width: BLUR_IMG_SIZE }
: { type: 'resize', height: BLUR_IMG_SIZE }
const resizedImage = await processBuffer(
content,
[resizeOperationOpts],
extension,
BLUR_QUALITY
function nextImageLoader(content) {
const imageLoaderSpan = this.currentTraceSpan.traceChild('next-image-loader')
return imageLoaderSpan.traceAsyncFn(async () => {
const isServer = loaderUtils.getOptions(this).isServer
const context = this.rootContext
const opts = { context, content }
const interpolatedName = loaderUtils.interpolateName(
this,
'/static/image/[path][name].[hash].[ext]',
opts
)
blurDataURL = `data:image/${extension};base64,${resizedImage.toString(
'base64'
)}`
}

const stringifiedData = JSON.stringify({
src: '/_next' + interpolatedName,
height: imageSize.height,
width: imageSize.width,
blurDataURL,
})

if (!isServer) {
this.emitFile(interpolatedName, content, null)
}
let extension = loaderUtils.interpolateName(this, '[ext]', opts)
if (extension === 'jpg') {
extension = 'jpeg'
}

const imageSizeSpan = imageLoaderSpan.traceChild('image-size-calculation')
const imageSize = imageSizeSpan.traceFn(() => sizeOf(content))
let blurDataURL
if (VALID_BLUR_EXT.includes(extension)) {
// Shrink the image's largest dimension
const resizeOperationOpts =
imageSize.width >= imageSize.height
? { type: 'resize', width: BLUR_IMG_SIZE }
: { type: 'resize', height: BLUR_IMG_SIZE }

const resizeImageSpan = imageLoaderSpan.traceChild('image-resize')
const resizedImage = await resizeImageSpan.traceAsyncFn(() =>
processBuffer(content, [resizeOperationOpts], extension, BLUR_QUALITY)
)
const blurDataURLSpan = imageLoaderSpan.traceChild(
'image-base64-tostring'
)
blurDataURL = blurDataURLSpan.traceFn(
() =>
`data:image/${extension};base64,${resizedImage.toString('base64')}`
)
}

return `${'export default '} ${stringifiedData};`
const stringifiedData = imageLoaderSpan
.traceChild('image-data-stringify')
.traceFn(() =>
JSON.stringify({
src: '/_next' + interpolatedName,
height: imageSize.height,
width: imageSize.width,
blurDataURL,
})
)

if (!isServer) {
this.emitFile(interpolatedName, content, null)
}

return `export default ${stringifiedData};`
})
}
export const raw = true
export default nextImageLoader

0 comments on commit 7c56684

Please sign in to comment.