Refactor next/image size handling

This commit is contained in:
Sam Becker 2023-11-24 13:04:38 -06:00
parent 043f733e22
commit 1ae5ed89b2
12 changed files with 34 additions and 21 deletions

View File

@ -10,7 +10,7 @@ const withBundleAnalyzer = require('@next/bundle-analyzer')({
const nextConfig = { const nextConfig = {
images: { images: {
imageSizes: [200, 400, 1050], imageSizes: [200],
remotePatterns: [{ remotePatterns: [{
protocol: 'https', protocol: 'https',
hostname: `${STORE_ID}.public.blob.vercel-storage.com`, hostname: `${STORE_ID}.public.blob.vercel-storage.com`,

View File

@ -5,7 +5,7 @@ import { uploadPhotoFromClient } from '@/services/blob';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { PATH_ADMIN_UPLOADS, pathForAdminUploadUrl } from '@/site/paths'; import { PATH_ADMIN_UPLOADS, pathForAdminUploadUrl } from '@/site/paths';
import ImageInput from '../components/ImageInput'; import ImageInput from '../components/ImageInput';
import { MAX_IMAGE_SIZE } from '@/utility/image'; import { MAX_IMAGE_SIZE } from '@/services/next-image';
import { cc } from '@/utility/css'; import { cc } from '@/utility/css';
export default function PhotoUpload({ export default function PhotoUpload({

View File

@ -4,6 +4,7 @@ import ImagePhotoGrid from './components/ImagePhotoGrid';
import ImageContainer from './components/ImageContainer'; import ImageContainer from './components/ImageContainer';
import { Camera, cameraFromPhoto } from '@/camera'; import { Camera, cameraFromPhoto } from '@/camera';
import { IoMdCamera } from 'react-icons/io'; import { IoMdCamera } from 'react-icons/io';
import { NextImageSize } from '@/services/next-image';
export default function CameraImageResponse({ export default function CameraImageResponse({
camera: cameraProp, camera: cameraProp,
@ -14,7 +15,7 @@ export default function CameraImageResponse({
}: { }: {
camera: Camera camera: Camera
photos: Photo[] photos: Photo[]
width: number width: NextImageSize
height: number height: number
fontFamily: string fontFamily: string
}) { }) {

View File

@ -8,6 +8,7 @@ import {
import PhotoFilmSimulationIcon from import PhotoFilmSimulationIcon from
'@/simulation/PhotoFilmSimulationIcon'; '@/simulation/PhotoFilmSimulationIcon';
import { FilmSimulation } from '@/simulation'; import { FilmSimulation } from '@/simulation';
import { NextImageSize } from '@/services/next-image';
export default function FilmSimulationImageResponse({ export default function FilmSimulationImageResponse({
simulation, simulation,
@ -18,7 +19,7 @@ export default function FilmSimulationImageResponse({
}: { }: {
simulation: FilmSimulation, simulation: FilmSimulation,
photos: Photo[] photos: Photo[]
width: number width: NextImageSize
height: number height: number
fontFamily: string fontFamily: string
}) { }) {

View File

@ -3,6 +3,7 @@ import { Photo } from '..';
import ImageCaption from './components/ImageCaption'; import ImageCaption from './components/ImageCaption';
import ImageContainer from './components/ImageContainer'; import ImageContainer from './components/ImageContainer';
import ImagePhotoGrid from './components/ImagePhotoGrid'; import ImagePhotoGrid from './components/ImagePhotoGrid';
import { NextImageSize } from '@/services/next-image';
export default function HomeImageResponse({ export default function HomeImageResponse({
photos, photos,
@ -11,7 +12,7 @@ export default function HomeImageResponse({
fontFamily, fontFamily,
}: { }: {
photos: Photo[] photos: Photo[]
width: number width: NextImageSize
height: number height: number
fontFamily: string fontFamily: string
}) { }) {

View File

@ -1,11 +1,11 @@
import { Photo } from '..'; import { Photo } from '..';
import { NextImageSize } from '@/utility/image';
import { formatModelShort } from '@/utility/exif'; import { formatModelShort } from '@/utility/exif';
import { AiFillApple } from 'react-icons/ai'; import { AiFillApple } from 'react-icons/ai';
import ImageCaption from './components/ImageCaption'; import ImageCaption from './components/ImageCaption';
import ImagePhotoGrid from './components/ImagePhotoGrid'; import ImagePhotoGrid from './components/ImagePhotoGrid';
import ImageContainer from './components/ImageContainer'; import ImageContainer from './components/ImageContainer';
import { OG_TEXT_BOTTOM_ALIGNMENT } from '@/site/config'; import { OG_TEXT_BOTTOM_ALIGNMENT } from '@/site/config';
import { NextImageSize } from '@/services/next-image';
export default function PhotoImageResponse({ export default function PhotoImageResponse({
photo, photo,

View File

@ -3,6 +3,7 @@ import { FaTag } from 'react-icons/fa';
import ImageCaption from './components/ImageCaption'; import ImageCaption from './components/ImageCaption';
import ImagePhotoGrid from './components/ImagePhotoGrid'; import ImagePhotoGrid from './components/ImagePhotoGrid';
import ImageContainer from './components/ImageContainer'; import ImageContainer from './components/ImageContainer';
import { NextImageSize } from '@/services/next-image';
export default function TagImageResponse({ export default function TagImageResponse({
tag, tag,
@ -13,7 +14,7 @@ export default function TagImageResponse({
}: { }: {
tag: string, tag: string,
photos: Photo[] photos: Photo[]
width: number width: NextImageSize
height: number height: number
fontFamily: string fontFamily: string
}) { }) {

View File

@ -2,6 +2,7 @@ import { Photo } from '..';
import IconFullFrame from '@/site/IconFullFrame'; import IconFullFrame from '@/site/IconFullFrame';
import IconGrid from '@/site/IconGrid'; import IconGrid from '@/site/IconGrid';
import ImagePhotoGrid from './components/ImagePhotoGrid'; import ImagePhotoGrid from './components/ImagePhotoGrid';
import { NextImageSize } from '@/services/next-image';
export default function TemplateImageResponse({ export default function TemplateImageResponse({
photos, photos,
@ -14,7 +15,7 @@ export default function TemplateImageResponse({
verticalOffset, verticalOffset,
}: { }: {
photos: Photo[] photos: Photo[]
width: number width: NextImageSize
height: number height: number
fontFamily: string fontFamily: string
outerMargin?: number outerMargin?: number
@ -89,7 +90,7 @@ export default function TemplateImageResponse({
}}> }}>
<ImagePhotoGrid {...{ <ImagePhotoGrid {...{
photos, photos,
width: innerWidth, widthArbitrary: innerWidth,
height: includeHeader height: includeHeader
? height - 130 - outerMargin * 2 ? height - 130 - outerMargin * 2
: height, : height,

View File

@ -1,28 +1,36 @@
/* eslint-disable jsx-a11y/alt-text */ /* eslint-disable jsx-a11y/alt-text */
import { Photo } from '@/photo'; import { Photo } from '@/photo';
import { getNextImageUrlForRequest } from '@/utility/image'; import {
NextImageSize,
getNextImageUrlForRequest,
} from '@/services/next-image';
export default function ImagePhotoGrid({ export default function ImagePhotoGrid({
photos, photos,
width, width,
widthArbitrary,
height, height,
imagePosition = 'center', imagePosition = 'center',
gap = 4, gap = 4,
}: { }: ({
photos: Photo[] photos: Photo[]
width: number
height: number height: number
imagePosition?: 'center' | 'top' imagePosition?: 'center' | 'top'
gap?: number gap?: number
}) { } & (
{ width: NextImageSize, widthArbitrary?: undefined } |
{ width?: undefined, widthArbitrary: number }
))) {
let count = 1; let count = 1;
if (photos.length >= 12) { count = 12; } if (photos.length >= 12) { count = 12; }
else if (photos.length >= 6) { count = 6; } else if (photos.length >= 6) { count = 6; }
else if (photos.length >= 4) { count = 4; } else if (photos.length >= 4) { count = 4; }
else if (photos.length >= 2) { count = 2; } else if (photos.length >= 2) { count = 2; }
const nextImageWidth = count <= 2 ? 1050 : 640; const nextImageWidth: NextImageSize = count <= 2
? width ?? 1080
: 640;
let rows = 1; let rows = 1;
if (count > 12) { rows = 4; } if (count > 12) { rows = 4; }
@ -31,7 +39,7 @@ export default function ImagePhotoGrid({
const imagesPerRow = count / rows; const imagesPerRow = count / rows;
const cellWidth = width / imagesPerRow - const cellWidth = (width ?? widthArbitrary) / imagesPerRow -
(imagesPerRow - 1) * gap / (imagesPerRow); (imagesPerRow - 1) * gap / (imagesPerRow);
const cellHeight= height / rows - const cellHeight= height / rows -
(rows - 1) * gap / rows; (rows - 1) * gap / rows;

View File

@ -1,4 +1,4 @@
import { NextImageSize } from '@/utility/image'; import { NextImageSize } from '@/services/next-image';
export const MAX_PHOTOS_TO_SHOW_OG = 12; export const MAX_PHOTOS_TO_SHOW_OG = 12;
export const MAX_PHOTOS_TO_SHOW_PER_TAG = 6; export const MAX_PHOTOS_TO_SHOW_PER_TAG = 6;
@ -7,7 +7,7 @@ export const MAX_PHOTOS_TO_SHOW_TEMPLATE_TIGHT = 12;
// 16:9 og image ratio // 16:9 og image ratio
const IMAGE_OG_RATIO = 16 / 9; const IMAGE_OG_RATIO = 16 / 9;
const IMAGE_OG_WIDTH: NextImageSize = 1200; const IMAGE_OG_WIDTH: NextImageSize = 1080;
const IMAGE_OG_HEIGHT = IMAGE_OG_WIDTH * (1 / IMAGE_OG_RATIO); const IMAGE_OG_HEIGHT = IMAGE_OG_WIDTH * (1 / IMAGE_OG_RATIO);
export const IMAGE_OG_SIZE = { export const IMAGE_OG_SIZE = {
width: IMAGE_OG_WIDTH, width: IMAGE_OG_WIDTH,
@ -16,7 +16,7 @@ export const IMAGE_OG_SIZE = {
}; };
// 16:9 og image ratio, small // 16:9 og image ratio, small
const IMAGE_OG_SMALL_WIDTH = 800; const IMAGE_OG_SMALL_WIDTH: NextImageSize = 828;
const IMAGE_OG_SMALL_HEIGHT = IMAGE_OG_SMALL_WIDTH * (1 / IMAGE_OG_RATIO); const IMAGE_OG_SMALL_HEIGHT = IMAGE_OG_SMALL_WIDTH * (1 / IMAGE_OG_RATIO);
export const IMAGE_OG_SMALL_SIZE = { export const IMAGE_OG_SMALL_SIZE = {
width: IMAGE_OG_SMALL_WIDTH, width: IMAGE_OG_SMALL_WIDTH,
@ -26,7 +26,7 @@ export const IMAGE_OG_SMALL_SIZE = {
// 3:2 og grid ratio // 3:2 og grid ratio
const GRID_OG_RATIO = 1.33; const GRID_OG_RATIO = 1.33;
const GRID_OG_WIDTH = 2000; const GRID_OG_WIDTH: NextImageSize = 2048;
const GRID_OG_HEIGHT = GRID_OG_WIDTH * (1 / GRID_OG_RATIO); const GRID_OG_HEIGHT = GRID_OG_WIDTH * (1 / GRID_OG_RATIO);
export const GRID_OG_SIZE = { export const GRID_OG_SIZE = {
width: GRID_OG_WIDTH, width: GRID_OG_WIDTH,

View File

@ -1,7 +1,7 @@
import { BASE_URL } from '@/site/config'; import { BASE_URL } from '@/site/config';
// Explicity defined next.config.js `imageSizes` // Explicity defined next.config.js `imageSizes`
type NextCustomSize = 200 | 400 | 1050; type NextCustomSize = 200;
type NextImageDeviceSize = 640 | 750 | 828 | 1080 | 1200 | 1920 | 2048 | 3840; type NextImageDeviceSize = 640 | 750 | 828 | 1080 | 1200 | 1920 | 2048 | 3840;
export type NextImageSize = NextCustomSize | NextImageDeviceSize; export type NextImageSize = NextCustomSize | NextImageDeviceSize;

View File

@ -1,7 +1,7 @@
import { Photo } from '@/photo'; import { Photo } from '@/photo';
import { absolutePathForPhoto } from './paths'; import { absolutePathForPhoto } from './paths';
import { formatDateFromPostgresString } from '@/utility/date'; import { formatDateFromPostgresString } from '@/utility/date';
import { getNextImageUrlForRequest } from '@/utility/image'; import { getNextImageUrlForRequest } from '@/services/next-image';
export const API_PHOTO_REQUEST_LIMIT = 20; export const API_PHOTO_REQUEST_LIMIT = 20;