@samitouri / QOS-React / commits / 78328c0c4d

Add support for preload media to ReactDOM (#28635)

This PR adds support for `media` option to `ReactDOM.preload()`, which is needed when images differ between screen sizes (for example mobile vs desktop)

Marius Craciunoiu committed Mar 28, 2024 at 11:04 UTC 78328c0c4d70c9b9ee4ad2d6a2319c95e628dd2d
3 files changed +87
packages/react-dom/src/__tests__/ReactDOMFloat-test.js
+85
@@ -4261,6 +4261,91 @@ body {
4261 );
4262 });
4263
4264 + it('should handle media on image preload', async () => {
4265 + function App({isClient}) {
4266 + ReactDOM.preload('/server', {
4267 + as: 'image',
4268 + imageSrcSet: '/server',
4269 + imageSizes: '100vw',
4270 + media: 'print and (min-width: 768px)',
4271 + });
4272 +
4273 + if (isClient) {
4274 + ReactDOM.preload('/client', {
4275 + as: 'image',
4276 + imageSrcSet: '/client',
4277 + imageSizes: '100vw',
4278 + media: 'screen and (max-width: 480px)',
4279 + });
4280 + }
4281 +
4282 + return (
4283 + <html>
4284 + <body>hello</body>
4285 + </html>
4286 + );
4287 + }
4288 +
4289 + await act(() => {
4290 + renderToPipeableStream(<App />).pipe(writable);
4291 + });
4292 + expect(getMeaningfulChildren(document)).toEqual(
4293 + <html>
4294 + <head>
4295 + <link
4296 + rel="preload"
4297 + as="image"
4298 + imagesrcset="/server"
4299 + imagesizes="100vw"
4300 + media="print and (min-width: 768px)"
4301 + />
4302 + </head>
4303 + <body>hello</body>
4304 + </html>,
4305 + );
4306 +
4307 + const root = ReactDOMClient.hydrateRoot(document, <App />);
4308 + await waitForAll([]);
4309 + expect(getMeaningfulChildren(document)).toEqual(
4310 + <html>
4311 + <head>
4312 + <link
4313 + rel="preload"
4314 + as="image"
4315 + imagesrcset="/server"
4316 + imagesizes="100vw"
4317 + media="print and (min-width: 768px)"
4318 + />
4319 + </head>
4320 + <body>hello</body>
4321 + </html>,
4322 + );
4323 +
4324 + root.render(<App isClient={true} />);
4325 + await waitForAll([]);
4326 + expect(getMeaningfulChildren(document)).toEqual(
4327 + <html>
4328 + <head>
4329 + <link
4330 + rel="preload"
4331 + as="image"
4332 + imagesrcset="/server"
4333 + imagesizes="100vw"
4334 + media="print and (min-width: 768px)"
4335 + />
4336 + <link
4337 + rel="preload"
4338 + as="image"
4339 + imagesrcset="/client"
4340 + imagesizes="100vw"
4341 + media="screen and (max-width: 480px)"
4342 + />
4343 + </head>
4344 + <body>hello</body>
4345 + </html>,
4346 + );
4347 + });
4348 +
4349 it('should warn if you preload a stylesheet and then render a style tag with the same href', async () => {
4350 const style = 'body { color: red; }';
4351 function App() {
packages/react-dom/src/shared/ReactDOMFloat.js
+1
@@ -139,6 +139,7 @@ export function preload(href: string, options: PreloadOptions) {
139 : undefined,
140 imageSizes:
141 typeof options.imageSizes === 'string' ? options.imageSizes : undefined,
142 + media: typeof options.media === 'string' ? options.media : undefined,
143 });
144 }
145 // We don't error because preload needs to be resilient to being called in a variety of scopes
packages/react-dom/src/shared/ReactDOMTypes.js
+1
@@ -16,6 +16,7 @@ export type PreloadOptions = {
16 crossOrigin?: string,
17 integrity?: string,
18 type?: string,
19 + media?: string,
20 nonce?: string,
21 fetchPriority?: FetchPriorityEnum,
22 imageSrcSet?: string,