@@ -6,6 +6,7 @@ import { Manifest } from "../manifest.gen.ts";
66export const PATH : `/live/invoke/${keyof Manifest [ "loaders" ] } ` =
77 "/live/invoke/website/loaders/image.ts" ;
88
9+ export type SetEarlyHint = ( hint : string ) => void ;
910export type Props =
1011 & Omit <
1112 JSX . IntrinsicElements [ "img" ] ,
@@ -23,6 +24,7 @@ export type Props =
2324 fetchPriority ?: "high" | "low" | "auto" ;
2425 /** @description Object-fit */
2526 fit ?: FitOptions ;
27+ setEarlyHint ?: SetEarlyHint ;
2628 } ;
2729
2830const FACTORS = [ 1 , 2 ] ;
@@ -80,8 +82,13 @@ const optimizeVTEX = (opts: OptimizationOptions) => {
8082 const [ slash , arquivos , ids , rawId , ...rest ] = src . pathname . split ( "/" ) ;
8183 const [ trueId , _w , _h ] = rawId . split ( "-" ) ;
8284
83- src . pathname = [ slash , arquivos , ids , `${ trueId } -${ width } -${ height } ` , ...rest ]
84- . join ( "/" ) ;
85+ src . pathname = [
86+ slash ,
87+ arquivos ,
88+ ids ,
89+ `${ trueId } -${ width } -${ height } ` ,
90+ ...rest ,
91+ ] . join ( "/" ) ;
8592
8693 return src . href ;
8794} ;
@@ -161,6 +168,34 @@ export const getSrcSet = (
161168 return srcSet . length > 0 ? srcSet . join ( ", " ) : undefined ;
162169} ;
163170
171+ export const getEarlyHintFromSrcProps = ( srcProps : {
172+ imagesrcset : string | undefined ;
173+ imagesizes : string | undefined ;
174+ fetchpriority : "high" | "low" | "auto" | undefined ;
175+ media : string | undefined ;
176+ src : string ;
177+ } ) => {
178+ const earlyHintParts = [ `<${ srcProps . src } >; rel=preload; as=image` ] ;
179+
180+ if ( srcProps ?. imagesrcset ) {
181+ earlyHintParts . push ( `; imagesrcset=${ srcProps . imagesrcset } ` ) ;
182+ }
183+
184+ if ( srcProps ?. imagesizes ) {
185+ earlyHintParts . push ( `; imagesizes=${ srcProps . imagesizes } ` ) ;
186+ }
187+
188+ if ( srcProps ?. fetchpriority ) {
189+ earlyHintParts . push ( `; fetchpriority=${ srcProps . fetchpriority } ` ) ;
190+ }
191+
192+ if ( srcProps ?. media ) {
193+ earlyHintParts . push ( `; media=${ srcProps . media } ` ) ;
194+ }
195+
196+ return earlyHintParts . join ( "" ) ;
197+ } ;
198+
164199const Image = forwardRef < HTMLImageElement , Props > ( ( props , ref ) => {
165200 const { preload, loading = "lazy" } = props ;
166201
@@ -173,12 +208,27 @@ const Image = forwardRef<HTMLImageElement, Props>((props, ref) => {
173208 const srcSet = props . srcSet ??
174209 getSrcSet ( props . src , props . width , props . height , props . fit ) ;
175210
176- const linkProps = srcSet && {
177- imagesrcset : srcSet ,
178- imagesizes : props . sizes ,
179- fetchpriority : props . fetchPriority ,
180- media : props . media ,
181- } ;
211+ const linkProps = srcSet &&
212+ ( {
213+ imagesrcset : srcSet ,
214+ imagesizes : props . sizes ,
215+ fetchpriority : props . fetchPriority ,
216+ media : props . media ,
217+ } as
218+ | ""
219+ | undefined
220+ | {
221+ imagesrcset : string ;
222+ imagesizes : string | undefined ;
223+ fetchpriority : "high" | "low" | "auto" | undefined ;
224+ media : string | undefined ;
225+ } ) ;
226+
227+ if ( ! IS_BROWSER && props . setEarlyHint && preload && linkProps ) {
228+ props . setEarlyHint (
229+ getEarlyHintFromSrcProps ( { ...linkProps , src : props . src } ) ,
230+ ) ;
231+ }
182232
183233 return (
184234 < >
0 commit comments