## External CDN Resource Usage

### Version Requirements

- Base library version `>=2.26.0`
- `@ray-js/ray` version `>=1.6.10`
- Developer tools version `>=0.8.4`
- **Cannot be used together with the Tuya CDN feature**

### Feature Description

To reduce the mini app package size, Ray provides an external CDN resource feature. You can upload static resources (images, audio, etc.) to a CDN. At runtime, local resource paths are automatically replaced with the corresponding CDN URLs for the current region.

### Uploading to a CDN

You must choose and configure your own CDN provider and upload the resources in advance. Common providers include:

- [Tencent Cloud CDN](https://cloud.tencent.com/product/cdn)
- [Alibaba Cloud CDN](https://www.aliyun.com/product/cdn)
- [AWS CloudFront](https://aws.amazon.com/cn/cloudfront/)
- [Cloudflare CDN](https://www.cloudflare.com/cdn/)

### Configure the CDN

Add a `cdn` directory (example under `src`) and create a `cdnImage.json` file. Example structure:

```
├── package.json
├── project.tuya.json
└── src
		└── cdn
				└── cdnImage.json
```

`cdnImage.json` must specify the CDN URL for each region code. Region codes to configure:

- AY: China
- AZ: United States
- EU: Europe (fallback)
- IN: India
- UE: U.S. East
- WE: Western Europe
- RU: Russia

```json
{
	"AY": {
		"/cdn/logo.png": "https://images.tuyacn.com/smart/miniapp/static/1664528993779f7997c9a.png",
		"/cdn/1.png": "https://images.tuyacn.com/smart/miniapp/static/1670384599c63a79781fd.png"
	},
	"AZ": {
		"/cdn/logo.png": "https://usimagesd1448c85ulz2o4.cdn5th.com/smart/miniapp/static/1664528993779f7997c9a.png",
		"/cdn/1.png": "https://usimagesd1448c85ulz2o4.cdn5th.com/smart/miniapp/static/1670384599c63a79781fd.png"
	},
	"EU": {
		"/cdn/logo.png": "https://euimagesd2h2yqnfpu4gl5.cdn5th.com/smart/miniapp/static/1664528993779f7997c9a.png",
		"/cdn/1.png": "https://euimagesd2h2yqnfpu4gl5.cdn5th.com/smart/miniapp/static/1670384599c63a79781fd.png"
	},
	"IN": {
		"/cdn/logo.png": "https://inimagesd1jqokb9wptk2t.cdn5th.com/smart/miniapp/static/1664528993779f7997c9a.png",
		"/cdn/1.png": "https://inimagesd1jqokb9wptk2t.cdn5th.com/smart/miniapp/static/1670384599c63a79781fd.png"
	},
	"UE": {
		"/cdn/logo.png": "https://usimagesd1448c85ulz2o4.cdn5th.com/smart/miniapp/static/1664528993779f7997c9a.png",
		"/cdn/1.png": "https://usimagesd1448c85ulz2o4.cdn5th.com/smart/miniapp/static/1670384599c63a79781fd.png"
	},
	"WE": {
		"/cdn/logo.png": "https://d2h2yqnfpu4gl5.cdn5th.com/smart/miniapp/static/1664528993779f7997c9a.png",
		"/cdn/1.png": "https://d2h2yqnfpu4gl5.cdn5th.com/smart/miniapp/static/1670384599c63a79781fd.png"
	},
	"RU": {
		"/cdn/logo.png": "https://euimagesd2h2yqnfpu4gl5.cdn5th.com/smart/miniapp/static/1664528993779f7997c9a.png",
		"/cdn/1.png": "https://euimagesd2h2yqnfpu4gl5.cdn5th.com/smart/miniapp/static/1670384599c63a79781fd.png"
	}
}
```

**Notes:**

1. CDN URLs in the configuration must match the actually uploaded resource URLs, otherwise replacement fails.
2. The Europe (EU) region acts as the fallback when a URL for another region is missing.

### Usage in the Project

Ray provides the `getCdnUrl` method. Image paths are automatically replaced with region-specific CDN URLs.

```tsx
import { getCdnUrl } from '@ray-js/ray'
import React from 'react'
import { Image, View, Text } from '@ray-js/ray'
import cdnImage from '@/cdn/cdnImage.json'

const imageStyles = {
	base: {
		display: 'block',
	},
	logo: {
		width: 100,
		height: 100,
		marginBottom: 20,
		borderRadius: 8,
		boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
	},
	banner: {
		width: 200,
		height: 200,
		borderRadius: 12,
		boxShadow: '0 4px 12px rgba(0,0,0,0.15)',
		border: '1px solid #eee',
	},
}

export default function Home() {
	// Preprocess CDN URLs to avoid repeated calls
	const logoUrl = getCdnUrl('/cdn/logo.png', cdnImage)
	const bannerUrl = getCdnUrl('/cdn/1.png', cdnImage)

	return (
		<View>
			<Text>Hello CDN</Text>
			<Image src={logoUrl} style={{ ...imageStyles.base, ...imageStyles.logo }} />
			<Image src={bannerUrl} style={{ ...imageStyles.base, ...imageStyles.banner }} />
		</View>
	)
}
```

