Skip to content

Commit

Permalink
Merge branch 'canary' into feat/fix-blur-image-position
Browse files Browse the repository at this point in the history
  • Loading branch information
styfle authored Jun 30, 2021
2 parents 7d055ce + 2373320 commit af602c7
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 223 deletions.
120 changes: 92 additions & 28 deletions packages/next/server/image-optimizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const PNG = 'image/png'
const JPEG = 'image/jpeg'
const GIF = 'image/gif'
const SVG = 'image/svg+xml'
const CACHE_VERSION = 2
const CACHE_VERSION = 3
const MODERN_TYPES = [/* AVIF, */ WEBP]
const ANIMATABLE_TYPES = [WEBP, PNG, GIF]
const VECTOR_TYPES = [SVG]
Expand All @@ -35,7 +35,8 @@ export async function imageOptimizer(
res: ServerResponse,
parsedUrl: UrlWithParsedQuery,
nextConfig: NextConfig,
distDir: string
distDir: string,
isDev = false
) {
const imageData: ImageConfig = nextConfig.images || imageConfigDefault
const { deviceSizes = [], imageSizes = [], domains = [], loader } = imageData
Expand Down Expand Up @@ -158,24 +159,24 @@ export async function imageOptimizer(
if (await fileExists(hashDir, 'directory')) {
const files = await promises.readdir(hashDir)
for (let file of files) {
const [prefix, etag, extension] = file.split('.')
const expireAt = Number(prefix)
const [maxAgeStr, expireAtSt, etag, extension] = file.split('.')
const maxAge = Number(maxAgeStr)
const expireAt = Number(expireAtSt)
const contentType = getContentType(extension)
const fsPath = join(hashDir, file)
if (now < expireAt) {
res.setHeader(
'Cache-Control',
isStatic
? 'public, max-age=315360000, immutable'
: 'public, max-age=0, must-revalidate'
const result = setResponseHeaders(
req,
res,
etag,
maxAge,
contentType,
isStatic,
isDev
)
if (sendEtagResponse(req, res, etag)) {
return { finished: true }
if (!result.finished) {
createReadStream(fsPath).pipe(res)
}
if (contentType) {
res.setHeader('Content-Type', contentType)
}
createReadStream(fsPath).pipe(res)
return { finished: true }
} else {
await promises.unlink(fsPath)
Expand Down Expand Up @@ -271,8 +272,22 @@ export async function imageOptimizer(
const animate =
ANIMATABLE_TYPES.includes(upstreamType) && isAnimated(upstreamBuffer)
if (vector || animate) {
await writeToCacheDir(hashDir, upstreamType, expireAt, upstreamBuffer)
sendResponse(req, res, upstreamType, upstreamBuffer, isStatic)
await writeToCacheDir(
hashDir,
upstreamType,
maxAge,
expireAt,
upstreamBuffer
)
sendResponse(
req,
res,
maxAge,
upstreamType,
upstreamBuffer,
isStatic,
isDev
)
return { finished: true }
}

Expand Down Expand Up @@ -342,13 +357,35 @@ export async function imageOptimizer(
}

if (optimizedBuffer) {
await writeToCacheDir(hashDir, contentType, expireAt, optimizedBuffer)
sendResponse(req, res, contentType, optimizedBuffer, isStatic)
await writeToCacheDir(
hashDir,
contentType,
maxAge,
expireAt,
optimizedBuffer
)
sendResponse(
req,
res,
maxAge,
contentType,
optimizedBuffer,
isStatic,
isDev
)
} else {
throw new Error('Unable to optimize buffer')
}
} catch (error) {
sendResponse(req, res, upstreamType, upstreamBuffer, isStatic)
sendResponse(
req,
res,
maxAge,
upstreamType,
upstreamBuffer,
isStatic,
isDev
)
}

return { finished: true }
Expand All @@ -362,37 +399,64 @@ export async function imageOptimizer(
async function writeToCacheDir(
dir: string,
contentType: string,
maxAge: number,
expireAt: number,
buffer: Buffer
) {
await promises.mkdir(dir, { recursive: true })
const extension = getExtension(contentType)
const etag = getHash([buffer])
const filename = join(dir, `${expireAt}.${etag}.${extension}`)
const filename = join(dir, `${maxAge}.${expireAt}.${etag}.${extension}`)
await promises.writeFile(filename, buffer)
}

function sendResponse(
function setResponseHeaders(
req: IncomingMessage,
res: ServerResponse,
etag: string,
maxAge: number,
contentType: string | null,
buffer: Buffer,
isStatic: boolean
isStatic: boolean,
isDev: boolean
) {
const etag = getHash([buffer])
res.setHeader(
'Cache-Control',
isStatic
? 'public, max-age=315360000, immutable'
: 'public, max-age=0, must-revalidate'
: `public, max-age=${isDev ? 0 : maxAge}, must-revalidate`
)
if (sendEtagResponse(req, res, etag)) {
return
// already called res.end() so we're finished
return { finished: true }
}
if (contentType) {
res.setHeader('Content-Type', contentType)
}
res.end(buffer)
return { finished: false }
}

function sendResponse(
req: IncomingMessage,
res: ServerResponse,
maxAge: number,
contentType: string | null,
buffer: Buffer,
isStatic: boolean,
isDev: boolean
) {
const etag = getHash([buffer])
const result = setResponseHeaders(
req,
res,
etag,
maxAge,
contentType,
isStatic,
isDev
)
if (!result.finished) {
res.end(buffer)
}
}

function getSupportedMimeType(options: string[], accept = ''): string {
Expand Down
3 changes: 2 additions & 1 deletion packages/next/server/next-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,8 @@ export default class Server {
res,
parsedUrl,
server.nextConfig,
server.distDir
server.distDir,
this.renderOpts.dev
),
},
{
Expand Down
38 changes: 19 additions & 19 deletions test/integration/build-output/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,44 +115,44 @@ describe('Build Output', () => {
expect(parseFloat(size)).toBeGreaterThan(0)
}

const gz = gzipSize !== false
// const gz = gzipSize !== false

expect(parseFloat(indexSize) / 1000).toBeCloseTo(
gz ? 0.251 : 0.394,
2
)
// expect(parseFloat(indexSize) / 1000).toBeCloseTo(
// gz ? 0.251 : 0.394,
// 2
// )
expect(indexSize.endsWith('B')).toBe(true)

expect(parseFloat(indexFirstLoad)).toBeCloseTo(gz ? 64 : 196, 1)
// expect(parseFloat(indexFirstLoad)).toBeCloseTo(gz ? 64 : 196, 1)
expect(indexFirstLoad.endsWith('kB')).toBe(true)

expect(parseFloat(err404Size)).toBeCloseTo(gz ? 3.17 : 8.51, 1)
// expect(parseFloat(err404Size)).toBeCloseTo(gz ? 3.17 : 8.51, 1)
expect(err404Size.endsWith('kB')).toBe(true)

expect(parseFloat(err404FirstLoad)).toBeCloseTo(gz ? 66.9 : 204, 1)
// expect(parseFloat(err404FirstLoad)).toBeCloseTo(gz ? 66.9 : 204, 1)
expect(err404FirstLoad.endsWith('kB')).toBe(true)

expect(parseFloat(sharedByAll)).toBeCloseTo(gz ? 63.7 : 196, 1)
// expect(parseFloat(sharedByAll)).toBeCloseTo(gz ? 63.7 : 196, 1)
expect(sharedByAll.endsWith('kB')).toBe(true)

const appSizeValue = _appSize.endsWith('kB')
? parseFloat(_appSize)
: parseFloat(_appSize) / 1000
expect(appSizeValue).toBeCloseTo(gz ? 0.799 : 1.63, 1)
// const appSizeValue = _appSize.endsWith('kB')
// ? parseFloat(_appSize)
// : parseFloat(_appSize) / 1000
// expect(appSizeValue).toBeCloseTo(gz ? 0.799 : 1.63, 1)
expect(_appSize.endsWith('kB') || _appSize.endsWith(' B')).toBe(true)

const webpackSizeValue = webpackSize.endsWith('kB')
? parseFloat(webpackSize)
: parseFloat(webpackSize) / 1000
expect(webpackSizeValue).toBeCloseTo(gz ? 0.766 : 1.46, 2)
// const webpackSizeValue = webpackSize.endsWith('kB')
// ? parseFloat(webpackSize)
// : parseFloat(webpackSize) / 1000
// expect(webpackSizeValue).toBeCloseTo(gz ? 0.766 : 1.46, 2)
expect(webpackSize.endsWith('kB') || webpackSize.endsWith(' B')).toBe(
true
)

expect(parseFloat(mainSize)).toBeCloseTo(gz ? 20.1 : 62.7, 1)
// expect(parseFloat(mainSize)).toBeCloseTo(gz ? 20.1 : 62.7, 1)
expect(mainSize.endsWith('kB')).toBe(true)

expect(parseFloat(frameworkSize)).toBeCloseTo(gz ? 42.0 : 130, 1)
// expect(parseFloat(frameworkSize)).toBeCloseTo(gz ? 42.0 : 130, 1)
expect(frameworkSize.endsWith('kB')).toBe(true)
})

Expand Down
Loading

0 comments on commit af602c7

Please sign in to comment.