Using the Optimized ShopifyImage Component
When creating custom blocks that are added through the Appmaker dashboard and registered in your theme, loading large images can impact performance. This is particularly important for blocks that display images uploaded through the dashboard's interface. The ShopifyImage
component provides an optimized solution by:
- Automatically resizing images before download using Shopify's image API
- Supporting both standard React Native Image and FastImage components
- Handling URL parameter management for image dimensions
Component Implementation
Create a new file ShopifyImage.tsx
in your theme's components directory and add the following code:
import React, { useMemo } from 'react';
import FastImage, { FastImageProps } from 'react-native-fast-image';
import { Image } from 'react-native';
// Safety check to ensure only Shopify CDN URLs are processed
// The dashboard will always provide Shopify image URLs, this is just a failsafe
const isValidUrl = (url: string): boolean => {
try {
if (url.includes(' ')) return false;
if (!url.startsWith('http://') && !url.startsWith('https://')) return false;
return url.includes('shopify.com');
} catch {
return false;
}
};
const appendQueryParam = (url: string, param: string, value: number): string => {
if (!url || !param) return url;
if (typeof value !== 'number' || value <= 0 || !Number.isFinite(value)) {
return url;
}
try {
const hasQuery = url.includes('?');
const hasTrailingQuery = url.endsWith('?');
const hasTrailingAmp = url.endsWith('&');
if (hasQuery) {
return `${url}${hasTrailingQuery || hasTrailingAmp ? '' : '&'}${param}=${value}`;
}
return `${url}?${param}=${value}`;
} catch {
return url;
}
};
interface ShopifyImageProps extends FastImageProps {
useFastImage?: boolean;
maxWidth?: number;
maxHeight?: number;
}
const ShopifyImage: React.FC<ShopifyImageProps> = ({
useFastImage = false,
maxWidth,
maxHeight,
source,
...props
}) => {
const modifiedSource = useMemo(() => {
if (!source || typeof source === 'number') return source;
try {
const { uri } = source;
if (!uri || typeof uri !== 'string') return source;
// Safety checks - dashboard always provides Shopify URLs
if (!uri.includes('shopify.com')) return source;
if (!isValidUrl(uri)) return source;
if (!maxWidth && !maxHeight) return source;
let newUri = uri;
if (maxWidth && maxWidth > 0) {
newUri = appendQueryParam(newUri, 'width', Math.floor(maxWidth));
}
if (maxHeight && maxHeight > 0) {
newUri = appendQueryParam(newUri, 'height', Math.floor(maxHeight));
}
if (newUri === uri) return source;
return {
...source,
uri: newUri,
};
} catch (error) {
console.warn('Error modifying Shopify image URL:', error);
return source;
}
}, [source, maxWidth, maxHeight]);
const ImageComponent = useFastImage ? FastImage : Image;
return <ImageComponent source={modifiedSource} {...props} />;
};
export default ShopifyImage;
Usage in Custom Blocks
To use the ShopifyImage
component in your custom blocks that are registered in the theme and configured through the Appmaker dashboard:
import { StyleSheet, View } from 'react-native'
import React from 'react'
import ShopifyImage from '../components/ShopifyImage';
type Props = {}
const DashboardImageBlock = (props: Props) => {
const { attributes } = props;
// The image URL will be provided by the dashboard when the block is configured
return (
<View>
<ShopifyImage
source={{
uri: attributes.image.url,
}}
maxWidth={300}
maxHeight={200}
useFastImage={true}
style={styles.image}
/>
</View>
);
};
export default DashboardImageBlock;
const styles = StyleSheet.create({
image: {
width: '100%',
height: 200,
},
});
Props
The ShopifyImage
component accepts all standard props from React Native's Image component plus these additional props:
Prop | Type | Default | Description |
---|---|---|---|
useFastImage | boolean | false | When true, uses react-native-fast-image instead of the standard Image component |
maxWidth | number | undefined | Maximum width to request from Shopify's image API |
maxHeight | number | undefined | Maximum height to request from Shopify's image API |
How It Works
- When configuring the block through the dashboard, you'll upload or select an image
- The dashboard provides a Shopify CDN URL as per the attribute settings from the block configuration
- The component includes safety checks to ensure only Shopify CDN URLs are processed
- If
maxWidth
ormaxHeight
are provided, it appends these parameters to the URL - Shopify's CDN will return an optimized image of the requested size
- This reduces the download size and improves performance
Best Practices
- Always specify both
maxWidth
andmaxHeight
to ensure optimal image sizing - Use
useFastImage={true}
for better performance with multiple images - Set appropriate style dimensions that match your maxWidth/maxHeight to avoid layout shifts
- Consider the device's screen density when setting dimensions