How to setup Sirv for PWA Studio
Tags: webdev, javascript
Published: 2020-08-12 15:27:27

This blog will show you the steps to setup Sirv with a PWA Studio 7.0.0 environment. This post expects you to already have an Sirv account ready.

#### Step 1: Configuring Magento
- Go to your magento backend and navigate to "Store -> General -> web"
- Change both "Base URL for User Media Files" and "Secure Base URL for User Media Files" to use your Sirv media url. For example: https://static.your-webshops.com/media/

#### Step 2: Change your `.env` file
- Go to your `.env` file located in the root of your pwa studio project
- Change `IMAGE_OPTIMIZING_ORIGIN` to `IMAGE_OPTIMIZING_ORIGIN=backend` 

> This will tell PWA Studio that we are going to use another image optimisation tool instead of the onboard image  optimisation

#### Step 3: Prepare the makeUrl file
- Open `@magento/venia-ui/lib/util/makeUrl.js` 
- We need to export `useBackendForImgs` change it so we get the following: `export const useBackendForImgs = imageOptimizingOrigin === 'backend';`
- Find the following code block:
```
    const params = new URLSearchParams(baseURL.search);
    params.set('auto', 'webp'); // Use the webp format if available

    const imageFileType = getFileType(baseURL);
    if (imageFileType === 'png') {
        params.set('format', 'png'); // use png if webp is not available
    } else {
        params.set('format', 'pjpg'); // Use progressive JPG if webp is not available
    }
```
And change it like shown below:
```
    const params = new URLSearchParams(baseURL.search);

    if (!useBackendForImgs) {
        params.set('auto', 'webp'); // Use the webp format if available

        const imageFileType = getFileType(baseURL);
        if (imageFileType === 'png') {
            params.set('format', 'png'); // use png if webp is not available
        } else {
            params.set('format', 'pjpg'); // Use progressive JPG if webp is not available
        }
    }
```

#### Step 4: Change the url params to be compliant with Sirv's format
- Open `@magento/venia-ui/lib/drivers/index.js`
- Change `export { default as resourceUrl } from '../util/makeUrl';` to `export { default as resourceUrl, useBackendForImgs } from '../util/makeUrl';`
- Open `@magento/venia-ui/lib/util/images.js`
- on line `1` import `useBackendForImgs` like so: `import { resourceUrl, useBackendForImgs } from '@magento/venia-drivers';`
- Replace the `generateUrl` function with the code below:
```
export const generateUrl = (imageURL, mediaBase) => (width, height) => {
    if (useBackendForImgs) {
        const regex = /cache\/.+?(?=\/)\//;
        const imageURLWithoutCacheKey = imageURL.replace(regex, '');
        return resourceUrl(imageURLWithoutCacheKey, {
            type: mediaBase,
            'scale.width': width,
            'scale.height': height,
        });
    }

    return resourceUrl(imageURL, {
        type: mediaBase,
        width,
        height,
        fit: 'cover',
    });
};
```
> NOTE: if the imageUrl doesn't has the cache key included you can remove the regex part. Also the regex is a dirty fix because the urls should come back from the API without the cache key. We only care about originals.

## That's it you've done it!

Well not quite yet :( if you open up chrome dev tools and open the 'Application -> Cache Storage' you should see (must have SW enabled) an entry called 'catalog - https://yourwebshop.com' this holds all catalog images.

The `Response-Type` for images will probably say `opaque` this will result in an extremely large sw storage size most likely it shows an error in the chrome console saying something like "the quota is exceeded". When the `Response-Type` is `opaque` it will reserve 7MB per image.

To fix this problem we need to make the following changes:
- Add `crossorigin="anonymous"` to all custom `img` elements like so: `<img crossorigin="anonymous" src="blabla" />`
- Open `src/ServiceWorker/Utilities/imageCacheHandler.js` and change line `98` from `mode: 'no-cors'` to `mode: 'anonymous'`
- Open `@magento/venia-ui/lib/components/Image/image.js`
- Add the prop `crossOrigin="anonymous"` to the `<SimpleImage` and `<ResourceImage` component.

## Congratulations! You now have Sirv working with PWA studio