templates: fix Media component failing when setting a custom serverURL (#12214)

### What?
Fixes #12171

### Why?
Previously, the ImageMedia component was not properly handling URL
formatting when a serverURL was configured in Payload. This caused
images to fail to load when using a custom serverURL. By extracting the
URL handling logic into a separate utility function, we ensure
consistent URL processing across both image and video components.

### How?
1. Created a new utility function getMediaUrl in
`src/utilities/getMediaUrl.ts` that:
   - Properly checks for HTTP/HTTPS protocols
   - Handles null or undefined URL values
   - Supports cache tags to prevent caching issues
   - Uses `getClientSideURL()` for relative paths
2. Updated the ImageMedia component to use this utility function instead
of inline URL processing logic
3. Updated the VideoMedia component to also use the same utility
function for consistency
This commit is contained in:
Rot4tion
2025-05-08 05:45:12 +07:00
committed by GitHub
parent b3cac753d6
commit 18693775e4
6 changed files with 48 additions and 8 deletions

View File

@@ -9,7 +9,7 @@ import React from 'react'
import type { Props as MediaProps } from '../types'
import { cssVariables } from '@/cssVariables'
import { getClientSideURL } from '@/utilities/getURL'
import { getMediaUrl } from '@/utilities/getMediaUrl'
const { breakpoints } = cssVariables
@@ -44,7 +44,7 @@ export const ImageMedia: React.FC<MediaProps> = (props) => {
const cacheTag = resource.updatedAt
src = `${getClientSideURL()}${url}?${cacheTag}`
src = getMediaUrl(url, cacheTag)
}
const loading = loadingFromProps || (!priority ? 'lazy' : undefined)

View File

@@ -5,7 +5,7 @@ import React, { useEffect, useRef } from 'react'
import type { Props as MediaProps } from '../types'
import { getClientSideURL } from '@/utilities/getURL'
import { getMediaUrl } from '@/utilities/getMediaUrl'
export const VideoMedia: React.FC<MediaProps> = (props) => {
const { onClick, resource, videoClassName } = props
@@ -37,7 +37,7 @@ export const VideoMedia: React.FC<MediaProps> = (props) => {
playsInline
ref={videoRef}
>
<source src={`${getClientSideURL()}/media/${filename}`} />
<source src={getMediaUrl(`/media/${filename}`)} />
</video>
)
}

View File

@@ -0,0 +1,20 @@
import { getClientSideURL } from '@/utilities/getURL'
/**
* Processes media resource URL to ensure proper formatting
* @param url The original URL from the resource
* @param cacheTag Optional cache tag to append to the URL
* @returns Properly formatted URL with cache tag if provided
*/
export const getMediaUrl = (url: string | null | undefined, cacheTag?: string | null): string => {
if (!url) return ''
// Check if URL already has http/https protocol
if (url.startsWith('http://') || url.startsWith('https://')) {
return cacheTag ? `${url}?${cacheTag}` : url
}
// Otherwise prepend client-side URL
const baseUrl = getClientSideURL()
return cacheTag ? `${baseUrl}${url}?${cacheTag}` : `${baseUrl}${url}`
}

View File

@@ -10,6 +10,7 @@ import type { Props as MediaProps } from '../types'
import { cssVariables } from '@/cssVariables'
import { getClientSideURL } from '@/utilities/getURL'
import { getMediaUrl } from '@/utilities/getMediaUrl'
const { breakpoints } = cssVariables
@@ -44,7 +45,7 @@ export const ImageMedia: React.FC<MediaProps> = (props) => {
const cacheTag = resource.updatedAt
src = `${getClientSideURL()}${url}?${cacheTag}`
src = getMediaUrl(url, cacheTag)
}
const loading = loadingFromProps || (!priority ? 'lazy' : undefined)

View File

@@ -4,8 +4,7 @@ import { cn } from '@/utilities/ui'
import React, { useEffect, useRef } from 'react'
import type { Props as MediaProps } from '../types'
import { getClientSideURL } from '@/utilities/getURL'
import { getMediaUrl } from '@/utilities/getMediaUrl'
export const VideoMedia: React.FC<MediaProps> = (props) => {
const { onClick, resource, videoClassName } = props
@@ -37,7 +36,7 @@ export const VideoMedia: React.FC<MediaProps> = (props) => {
playsInline
ref={videoRef}
>
<source src={`${getClientSideURL()}/media/${filename}`} />
<source src={getMediaUrl(`/media/${filename}`)} />
</video>
)
}

View File

@@ -0,0 +1,20 @@
import { getClientSideURL } from '@/utilities/getURL'
/**
* Processes media resource URL to ensure proper formatting
* @param url The original URL from the resource
* @param cacheTag Optional cache tag to append to the URL
* @returns Properly formatted URL with cache tag if provided
*/
export const getMediaUrl = (url: string | null | undefined, cacheTag?: string | null): string => {
if (!url) return ''
// Check if URL already has http/https protocol
if (url.startsWith('http://') || url.startsWith('https://')) {
return cacheTag ? `${url}?${cacheTag}` : url
}
// Otherwise prepend client-side URL
const baseUrl = getClientSideURL()
return cacheTag ? `${baseUrl}${url}?${cacheTag}` : `${baseUrl}${url}`
}