I discovered Astro recently and fell in love with it. Sorry Nuxt.js.
I re-did a marketing website ixmage.com and went away from Nuxt.js
, which was giving me SPA behavior and required ”enhancing” it with multiple
add-ons to make it behave like a normal website.
Because the site was mainly Vue
, and is not very big, it took me like 2 days to convert over to Astro.
I grabbed this image from unsplash.com and searched for pokemon, it is 2.5 MB in size, with dimensions of 5184x3456. I have placed it here with a width="300"
<img src="https://images.unsplash.com/photo-1596743343697-bd2c1e5a8c81" width="300" />
Using the original image, and telling the browser to display it at 300px width. This will download the
2.5MB image. The original image is of type image/jpeg
.
Using the same src, but with the Ixmage
component
<Ixmage src="https://images.unsplash.com/photo-1596743343697-bd2c1e5a8c81" width="300" token="TQKkCpGYGK" />
Requesting the same image, but leveraging the ixmage service.
Because I am using Microsoft Edge browser, the image came back as image/webp
.
The image size is 8.6 kB.
<Ixmage src="https://images.unsplash.com/photo-1596743343697-bd2c1e5a8c81" width="300" format="jpg" token="..." />
Above, explicitly requesting the image to be image/jpg
comes back in a size of 11.9 kB.
Version 1.0 is done in vue
.
It does not require client-side interactivity so no vue javascript
is bundled.
The ixmage service brings into play a CDN, and the image optimization processing. Ixmage will
also choose to deliver a webp
image when the browser hints its capabilities, but this can be overriden by explicitly asking for a format
.
<template>
<img :src="theurl" :width="width" :height="height" :alt="alt" :title="title||alt||''" />
</template>
<script>
export default {
props: {
token: { type: String, required: true },
src: { type: String, required: true },
alt: { type: String, required: false },
width: { type: String, required: false },
height: { type: String, required: false },
title: { type: String, required: false },
bgc: { type: String, default: 'transparent' },
format: { type: String, default: '' },
flip: { type: Boolean, default: false },
flop: { type: Boolean, default: false },
quality: { type: Number, default: 0 },
behavior: { type: String, default: '' },
allowenl: { type: Boolean, default: false },
sharpen: { type: Boolean, default: false },
dpr: { type: Number, required: false },
pixelate: { type: Number, default: 0 },
blur: { type: Number, default: 0 },
brightness: { type: Number, default: 0 },
hue: { type: Number, default: 0 },
saturation: { type: Number, default: 0 },
sepia: { type: Number, default: 0 },
grayscale: { type: Boolean, default: false },
},
data () {
return {
baseUri: 'https://cdn.ixmage.com/v2/'
};
},
computed: {
theurl () {
let xfs = '?v=1';
if (this.width) xfs += `&w=${this.width}`;
if (this.height) xfs += `&h=${this.height}`;
if (this.format) xfs += `&f=${this.format}`;
if (this.format.toLowerCase() === 'jpg') xfs += '&fmt=jpg';
if (this.format.toLowerCase() === 'png') xfs += '&fmt=png';
if (this.format.toLowerCase() === 'gif') xfs += '&fmt=gif';
if (this.format.toLowerCase() === 'webp') xfs += '&fmt=webp';
if (this.allowenl) xfs += `&allowenl=1`;
if (this.sharpen) xfs += `&sharp=1`;
if (this.flip) xfs += `&flip=1`;
if (this.flop) xfs += `&flop=1`;
if (this.quality) xfs += `&q=${this.quality}`;
if (this.behavior.toLowerCase() === 'extend') xfs += `&extend=1`;
if (this.behavior.toLowerCase() === 'cover') xfs += `&cover=1`;
if (this.dpr) xfs += `&dpr=${this.dpr}`;
if (this.pixelate && this.pixelate !== '0') xfs += `&pixelate=${this.pixelate}`;
if (this.blur && this.blur !== '0') xfs += `&blur=${this.blur}`;
if (this.brightness) xfs += `&mod=${this.brightness}`;
if (this.hue) xfs += `&hue=${this.hue}`;
if (this.saturation) xfs += `&sat=${this.saturation}`;
if (this.sepia) xfs += `&sepia=${this.sepia}`;
if (this.grayscale) xfs += `&grey=1`;
xfs += `&bgc=${this.bgc}`;
return this.baseUri + this.token + '/' + this.src + xfs;
}
}
}
</script>
The template portion is just an img
tag and its main attributes.
A later version will make it a bit more complex to allow setting a source set to specify a list of sizes so the browser can pick the best one for the situation.
The script portion defines the exposed properties to work on the image. Then, it has the logic to build the image src url that will be used.
Once you’ve pasted the component code above into /src/components/Ixmage.vue
you can then use it in your astro files like:
---
import Ixmage from './../components/Ixmage.vue';
---
<Ixmage src="url-to-image" width="300" token="TtAaCcOoSs" />
The token
you will grab from your ixmage account.
Once you familiarize yourself with how ixmage accesses your images, you could mount an alias
onto your domain. Let’s say you name the alias my-images
and you
have an image at https://my-domain.com/my-logo.png
, then you could access the image like:
<Ixmage src="/my-images/my-logo.png" token="..." />
and the generated url would be https://cdn.ixmage.com/v2/<token>/my-images/my-logo.png
prop | info |
---|---|
token | required Your ixmage account token. |
src | required url to your image. |
width | Image width, for both the image and the browser. |
height | Image height, for both the image and the browser. |
alt | Alt Text. |
prop | info |
---|---|
title | Caption for the img tag title; used as alt text when alt text not supplied. |
bgc | Background color for the image in case padding is needed. Defaults to transparent |
format | In case you need your image in this format, else the format will be set automatically depending on the requesting browser capabilites. |
quality | Set the quality percentage for JPG or WEBP. |
behavior | Allowed values are extend and cover |
allowenl | Allow the image to grow more than its original size. |
dpr | … |
prop | info |
---|---|
flip | Vertical mirror reflection of the image. |
flop | Horizontal mirror reflection of the image. |
sharpen | Sharpen the resulting image; may enhance the image when the resizing is very drastic. |
pixelate | Pixelation effect |
blur | Blur effect |
brightness | Adjust image brightness |
hue | Adjust image hue |
saturation | Adjust image saturation |
sepia | Sepia effect |
grayscale | Grayscale effect |