<commit_before>import loaderUtils from 'next/dist/compiled/loader-utils'
import sizeOf from 'image-size'
import { processBuffer } from '../../../server/lib/squoosh/main'

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
    )
    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)
  }

  return `${'export default '} ${stringifiedData};`
}
export const raw = true
export default nextImageLoader
<commit_msg>Add performance tracing for next-image-loader (#27043)<commit_after>import loaderUtils from 'next/dist/compiled/loader-utils'
import sizeOf from 'image-size'
import { processBuffer } from '../../../server/lib/squoosh/main'

const BLUR_IMG_SIZE = 8
const BLUR_QUALITY = 70
const VALID_BLUR_EXT = ['jpeg', 'png', 'webp']

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
    )

    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')}`
      )
    }

    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

{'fraction_non_alphanumeric': 0.1222707423580786, 'fraction_numerical': 0.005394297456974056, 'mean_word_length': 3.3027624309392265, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6643906', 'n_tokens_mistral': 1225, 'n_tokens_neox': 1180, 'n_words': 251}