rsnext/packages/next/build/webpack/loaders/next-image-loader.js
Alex Castle 277061943a
Don't emit duplicate image files (#26843)
fixes #26607

This change makes it so the image loader plugin only emits a file while processing an image import for the client. The final generated image URL was already the same in SSR and CSR anyway, so this change doesn't have any functional impact.

I also changed the name of the static page in the image component tests, since it was causing some conflicts with the static assets folder.
2021-07-02 11:27:32 +00:00

57 lines
1.5 KiB
JavaScript

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