mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-12 22:13:05 +00:00
fix(images): masters do hero no tamanho de exibição e TTL de 4h no otimizador
This commit is contained in:
parent
9a049bbbb4
commit
16f959752a
9 changed files with 94 additions and 7 deletions
|
|
@ -7,6 +7,7 @@ const nextConfig = {
|
|||
distDir: process.env.NEXT_DIST_DIR || '.next',
|
||||
...(process.env.NEXT_OUTPUT_STANDALONE === '1' ? { output: 'standalone' } : {}),
|
||||
images: {
|
||||
minimumCacheTTL: 14400,
|
||||
remotePatterns: [
|
||||
new URL(`${allowedImageHost}/**`),
|
||||
// YouTube video thumbnails (campaign home content board, S2) come from
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
BIN
public/Lula.avif
BIN
public/Lula.avif
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -5,31 +5,32 @@ const SUPPORT_URL = 'https://apoiar.me/jorgesolla'
|
|||
const allyImages = [
|
||||
{
|
||||
id: 'rui',
|
||||
src: '/RUI%20-%202-2.avif',
|
||||
src: '/RUI - 2-2.avif',
|
||||
width: 177,
|
||||
height: 265,
|
||||
sizes: '(min-width: 1366px) calc(6.14vw + 93px), 177px',
|
||||
sizes: '(min-width: 1920px) 211px, (min-width: 1366px) calc(6.14vw + 93px), 177px',
|
||||
},
|
||||
{
|
||||
id: 'wagner',
|
||||
src: '/WAGNER%20-%202-9%20final.avif',
|
||||
src: '/WAGNER - 2-9 final.avif',
|
||||
width: 177,
|
||||
height: 265,
|
||||
sizes: '(min-width: 1366px) calc(6.14vw + 93px), 177px',
|
||||
sizes: '(min-width: 1920px) 211px, (min-width: 1366px) calc(6.14vw + 93px), 177px',
|
||||
},
|
||||
{
|
||||
id: 'jeronimo',
|
||||
src: '/Jeronimo.avif',
|
||||
width: 177,
|
||||
height: 265,
|
||||
sizes: '(min-width: 1366px) calc(6.14vw + 93px), 177px',
|
||||
sizes: '(min-width: 1920px) 211px, (min-width: 1366px) calc(6.14vw + 93px), 177px',
|
||||
},
|
||||
{
|
||||
id: 'lula',
|
||||
src: '/Lula.avif',
|
||||
width: 216,
|
||||
height: 213,
|
||||
sizes: '(min-width: 1366px) calc(8.3vw + 125px), (min-width: 1024px) 238px, 216px',
|
||||
sizes:
|
||||
'(min-width: 1920px) 284px, (min-width: 1366px) calc(8.3vw + 124.6px), (min-width: 1024px) 238px, 216px',
|
||||
},
|
||||
]
|
||||
|
||||
|
|
@ -71,7 +72,7 @@ export const CampaignHero = () => (
|
|||
alt="Jorge Solla, candidato a deputado federal pela Bahia"
|
||||
width={495}
|
||||
height={742}
|
||||
sizes="(min-width: 1720px) 747px, (min-width: 1280px) 595px, (min-width: 1024px) 495px, 449px"
|
||||
sizes="(min-width: 1920px) 747px, (min-width: 1024px) calc(28.16vw + 206.7px), 449px"
|
||||
priority
|
||||
className="campaign-hero-portrait-image absolute h-auto max-w-none object-contain"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -31,6 +31,19 @@ describe('CampaignHero', () => {
|
|||
expect(novidadesLink.getAttribute('data-cta')).toBe('secondary')
|
||||
})
|
||||
|
||||
it('não percent-encoda os caminhos das imagens', () => {
|
||||
const { container } = render(<CampaignHero />)
|
||||
|
||||
const sources = Array.from(container.querySelectorAll('img')).map((image) =>
|
||||
image.getAttribute('src'),
|
||||
)
|
||||
expect(sources.length).toBeGreaterThan(0)
|
||||
|
||||
for (const source of sources) {
|
||||
expect(source).not.toContain('%')
|
||||
}
|
||||
})
|
||||
|
||||
it('expõe as provas e as fotos com nomes acessíveis', () => {
|
||||
render(<CampaignHero />)
|
||||
|
||||
|
|
|
|||
72
tests/unit/imageDelivery.unit.spec.ts
Normal file
72
tests/unit/imageDelivery.unit.spec.ts
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
// @vitest-environment node
|
||||
|
||||
import { existsSync, readFileSync, readdirSync } from 'node:fs'
|
||||
import { join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
import sharp from 'sharp'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
const MAX_WIDTH = 1600
|
||||
const MAX_HEIGHT = 2400
|
||||
|
||||
const LOCAL_IMAGE_REF = /src[=:]\s*['"](\/[^'"`]+\.(?:avif|webp|png|jpe?g))['"]/g
|
||||
|
||||
const publicFile = (src: string) =>
|
||||
fileURLToPath(new URL(`../../public${decodeURIComponent(src)}`, import.meta.url))
|
||||
|
||||
const campaignHeroSource = readFileSync(
|
||||
fileURLToPath(new URL('../../src/components/CampaignHero.tsx', import.meta.url)),
|
||||
'utf8',
|
||||
)
|
||||
|
||||
const localHeroAssets = [
|
||||
...new Set([...campaignHeroSource.matchAll(LOCAL_IMAGE_REF)].map(([, src]) => src)),
|
||||
]
|
||||
|
||||
const collectSourceImageRefs = () => {
|
||||
const refs = new Set<string>()
|
||||
const srcDir = fileURLToPath(new URL('../../src', import.meta.url))
|
||||
|
||||
for (const entry of readdirSync(srcDir, { recursive: true, withFileTypes: true })) {
|
||||
if (!entry.isFile() || !/\.(?:ts|tsx)$/.test(entry.name)) continue
|
||||
const code = readFileSync(join(entry.parentPath, entry.name), 'utf8')
|
||||
for (const [, src] of code.matchAll(LOCAL_IMAGE_REF)) refs.add(src)
|
||||
}
|
||||
|
||||
return refs
|
||||
}
|
||||
|
||||
describe('entrega das imagens do hero (perf do /_next/image)', () => {
|
||||
it('usa masters no tamanho máximo de exibição, sem forçar decode de 3840px', async () => {
|
||||
expect(localHeroAssets.length).toBeGreaterThanOrEqual(5)
|
||||
|
||||
for (const src of localHeroAssets) {
|
||||
const { width, height } = await sharp(publicFile(src)).metadata()
|
||||
expect(width, src).toBeLessThanOrEqual(MAX_WIDTH)
|
||||
expect(height, src).toBeLessThanOrEqual(MAX_HEIGHT)
|
||||
}
|
||||
})
|
||||
|
||||
it('mantém todo asset local entregue via next/image dentro do orçamento', async () => {
|
||||
const refs = [...collectSourceImageRefs()].filter((src) => existsSync(publicFile(src)))
|
||||
expect(refs.length).toBeGreaterThan(0)
|
||||
|
||||
for (const src of refs) {
|
||||
const { width, height } = await sharp(publicFile(src)).metadata()
|
||||
expect(width, src).toBeLessThanOrEqual(MAX_WIDTH)
|
||||
expect(height, src).toBeLessThanOrEqual(MAX_HEIGHT)
|
||||
}
|
||||
})
|
||||
|
||||
it('configura TTL longo para os derivados do otimizador', () => {
|
||||
const nextConfig = readFileSync(
|
||||
fileURLToPath(new URL('../../next.config.mjs', import.meta.url)),
|
||||
'utf8',
|
||||
)
|
||||
|
||||
const ttl = nextConfig.match(/minimumCacheTTL:\s*(\d+)/)
|
||||
expect(ttl, 'next.config.mjs deve definir images.minimumCacheTTL').toBeTruthy()
|
||||
expect(Number(ttl?.[1])).toBeGreaterThanOrEqual(3600)
|
||||
})
|
||||
})
|
||||
Loading…
Reference in a new issue