|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: How to use AVIF in Appwrite Storage |
| 4 | +description: Learn how to use AVIF, a new image format that offers better compression without sacrificing image quality, in Appwrite Storage. |
| 5 | +date: 2025-05-22 |
| 6 | +cover: /images/blog/avif-in-storage/cover.png |
| 7 | +timeToRead: 6 |
| 8 | +author: ebenezer-don |
| 9 | +category: tutorial |
| 10 | +featured: false |
| 11 | +--- |
| 12 | + |
| 13 | +Every web developer knows the struggle with image optimization. You want your images to look good, but large file sizes slow down your sites and hurt the user experience. JPEG and WebP have been popular choices for image compression, but they have limitations when it comes to achieving high compression without sacrificing image quality. AVIF offers a solution to this problem. |
| 14 | + |
| 15 | +Built on the [AV1 video codec](https://en.wikipedia.org/wiki/AV1) by the Alliance for Open Media, it gives us much better compression without the quality loss we're used to seeing in highly compressed images. |
| 16 | + |
| 17 | +Now that Appwrite supports [AVIF in Storage](/blog/post/new-image-formats-avif-heic), you can start using it in your projects. This matters because you can reduce image sizes by 50% or more compared to JPEG, while keeping the same visual quality. And for users with browsers that don't support AVIF yet, you can easily fall back to other formats. |
| 18 | + |
| 19 | +Let's learn how AVIF works in Appwrite and look at some real implementation examples. |
| 20 | + |
| 21 | +# What makes AVIF different? |
| 22 | + |
| 23 | +AVIF brings several technical improvements to image compression: |
| 24 | + |
| 25 | +- Achieves [better compression](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types) than JPEG and WebP while maintaining quality |
| 26 | +- Preserves more image detail at similar file sizes |
| 27 | +- Includes alpha channel for transparency |
| 28 | +- Works with wide color gamut (supports both HDR and standard color ranges) |
| 29 | +- Supports animations and image sequences |
| 30 | +- Supported by major browsers including Chrome and Firefox |
| 31 | + |
| 32 | +# Implementation in Appwrite |
| 33 | + |
| 34 | +Appwrite's Storage service provides three main ways to work with AVIF: |
| 35 | + |
| 36 | +- Direct AVIF file storage |
| 37 | +- On-demand conversion from other formats |
| 38 | +- Format-specific delivery based on browser support |
| 39 | + |
| 40 | +Let's examine each approach in detail. |
| 41 | + |
| 42 | +## Direct AVIF upload |
| 43 | + |
| 44 | +You can upload AVIF images to Appwrite Storage just like any other supported image format. |
| 45 | + |
| 46 | +Here's an example using the Web SDK: |
| 47 | + |
| 48 | +```js |
| 49 | +import { Client, Storage, ID } from "appwrite"; |
| 50 | + |
| 51 | +const client = new Client() |
| 52 | + .setEndpoint('<https://cloud.appwrite.io/v1>') |
| 53 | + .setProject('<PROJECT_ID>'); |
| 54 | + |
| 55 | +const storage = new Storage(client); |
| 56 | + |
| 57 | +// Upload an AVIF file |
| 58 | +const promise = storage.createFile( |
| 59 | + '<BUCKET_ID>', |
| 60 | + ID.unique(), |
| 61 | + document.getElementById('uploader').files[0] |
| 62 | +); |
| 63 | + |
| 64 | +promise.then(function (response) { |
| 65 | + console.log(response); |
| 66 | +}, function (error) { |
| 67 | + console.log(error); |
| 68 | +}); |
| 69 | +``` |
| 70 | + |
| 71 | +This code handles file upload through a standard form input. The Storage service accepts AVIF files just like any other supported image format, with no special handling required at the upload stage. |
| 72 | + |
| 73 | +## Converting images to AVIF |
| 74 | + |
| 75 | +Appwrite's Storage service can convert your existing images to AVIF format on demand. This means you can transform JPEGs, PNGs, and other formats to AVIF without preprocessing them. |
| 76 | + |
| 77 | +Here's how to implement the conversion: |
| 78 | + |
| 79 | +```js |
| 80 | +import { Client, Storage, ImageGravity, ImageFormat } from "appwrite"; |
| 81 | + |
| 82 | +const client = new Client() |
| 83 | + .setEndpoint('<https://cloud.appwrite.io/v1>') |
| 84 | + .setProject('<PROJECT_ID>'); |
| 85 | + |
| 86 | +const storage = new Storage(client); |
| 87 | + |
| 88 | +const result = storage.getFilePreview( |
| 89 | + '<BUCKET_ID>', // bucketId |
| 90 | + '<FILE_ID>', // fileId |
| 91 | + 2000, // width |
| 92 | + 0, // height (maintain aspect ratio) |
| 93 | + ImageGravity.Center, // gravity |
| 94 | + 100, // quality |
| 95 | + 0, // borderWidth |
| 96 | + '', // borderColor |
| 97 | + 0, // borderRadius |
| 98 | + 1, // opacity |
| 99 | + 0, // rotation |
| 100 | + '', // background |
| 101 | + ImageFormat.Avif // output format |
| 102 | +); |
| 103 | +``` |
| 104 | + |
| 105 | +The quality parameter in getFilePreview ranges from 0-100. AVIF's compression algorithm processes different image types (photographs, illustrations, UI elements) with varying efficiency, so quality settings need to be tested for your specific use case. |
| 106 | + |
| 107 | +The `ImageGravity` enum determines how images are cropped or positioned during resizing - `Center` maintains focus on the middle of the image. |
| 108 | + |
| 109 | +The `ImageFormat` enum specifies the output format, with options including `Avif`, `Webp`, `Jpg`, and `Png`. |
| 110 | + |
| 111 | +## Browser compatibility detection |
| 112 | + |
| 113 | +To ensure the best experience for all users, you should check for AVIF support before serving AVIF images. |
| 114 | + |
| 115 | +Here's a simple way to detect AVIF support: |
| 116 | + |
| 117 | +```js |
| 118 | +async function isAvifSupported() { |
| 119 | + const avif = new Image(); |
| 120 | + return new Promise((resolve) => { |
| 121 | + avif.onload = () => resolve(true); |
| 122 | + avif.onerror = () => resolve(false); |
| 123 | + avif.src = "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A="; |
| 124 | + }); |
| 125 | +} |
| 126 | + |
| 127 | +// Usage |
| 128 | +if (await isAvifSupported()) { |
| 129 | + // Serve AVIF images |
| 130 | +} else { |
| 131 | + // Fallback to WebP or JPEG |
| 132 | +} |
| 133 | +``` |
| 134 | + |
| 135 | +This code tries to load a tiny base64-encoded AVIF image in the browser. If the image loads successfully (onload), the browser supports AVIF. If it fails to load (onerror), it means the browser can't decode AVIF images and we need to use a fallback format |
| 136 | + |
| 137 | +## Implementing a format fallback |
| 138 | + |
| 139 | +We can use the `isAvifSupported` function to implement progressive enhancement for image loading. This means using a baseline format (in this case, WebP) and using AVIF for browsers that support it. |
| 140 | + |
| 141 | +Here's an example: |
| 142 | + |
| 143 | +```js |
| 144 | +const storage = new Storage(client); |
| 145 | + |
| 146 | +async function getOptimizedImageUrl(bucketId, fileId) { |
| 147 | + |
| 148 | + const format = await isAvifSupported() ? ImageFormat.Avif : ImageFormat.WebP; |
| 149 | + |
| 150 | + return storage.getFilePreview( |
| 151 | + bucketId, |
| 152 | + fileId, |
| 153 | + 1200, // width |
| 154 | + 0, // height |
| 155 | + 'center', // gravity |
| 156 | + 90, // quality |
| 157 | + 0, // border width |
| 158 | + '', // border color |
| 159 | + 0, // border radius |
| 160 | + 1, // opacity |
| 161 | + 0, // rotation |
| 162 | + '', // background |
| 163 | + format // output format |
| 164 | + ); |
| 165 | +} |
| 166 | +``` |
| 167 | + |
| 168 | +Notice that the format variable falls back to WebP if the browser doesn't support AVIF. I've used WebP because it's now widely supported. However, you can choose to fallback to JPEG for an even wider range of compatibility. |
| 169 | + |
| 170 | +# Best practices for using AVIF in Appwrite Storage |
| 171 | + |
| 172 | +When working with AVIF in Appwrite Storage, consider these best practices: |
| 173 | + |
| 174 | +1. **Progressive enhancement**: Always implement fallbacks for browsers that don't support AVIF. |
| 175 | +2. **Quality settings**: AVIF provides good quality even at lower settings. Start with a quality setting of 75-85 and adjust based on your needs. |
| 176 | +3. **Responsive images**: Use appropriate image dimensions for different screen sizes to optimize bandwidth usage. |
| 177 | +4. **Performance monitoring**: Monitor your application's performance metrics after implementing AVIF to ensure it provides the expected benefits. |
| 178 | +5. **Lazy loading**: Consider implementing lazy loading for AVIF images to further optimize page load performance. |
| 179 | + |
| 180 | +# Conclusion |
| 181 | + |
| 182 | +AVIF support in Appwrite Storage is a practical way to make your apps faster without compromising on image quality. The code to implement it is straightforward, and the benefits are real - especially for image-heavy applications. |
| 183 | + |
| 184 | +Start with a few test images, measure the results, and scale up from there. Your users will get faster load times, and you'll cut down on bandwidth costs. |
| 185 | + |
| 186 | +For more details on handling images in Appwrite, check out the [Storage documentation](/docs/products/storage/quick-start). |
| 187 | + |
| 188 | +# Further reading |
| 189 | + |
| 190 | +- [How Appwrite streamlines database operations using hooks](/blog/post/hooks-appwrite-databases?doFollow=true) |
| 191 | +- [5 VS Code extensions that replace entire development tools](/blog/post/5-vs-code-extensions-that-replace-entire-dev-tools?doFollow=true) |
| 192 | +- [Budget caps: How to stop unexpected cloud bills before they happen](/blog/post/budget-caps-stop-unexpected-cloud-bills?doFollow=true) |
0 commit comments