On Servd, local asset volumes aren't guaranteed to persist over any extended period of time - it's one of the ways we make high availability work on every project.
To help you set up an alternative to local volumes we created the Servd Asset Platform and the Servd Assets and Helpers Plugin which provide an easy to use asset storage solution, along with a host of other useful bits of functionality.
Installing The Plugin With Composer
The preferred method of installing the plugin is via `composer` on the command line. The following will add he latest version of the plugin to your project:
composer require servd/craft-asset-storage
Once downloaded you'll also need to enable the plugin on Craft's Plugin settings page.
Installing The Plugin Via The Control Panel
Navigate to the Plugin Store in the Craft control panel
Search for 'Servd'
Select the 'Servd Assets and Helpers' plugin, scroll down and click 'Install'
Getting Started
If you would like to use Servd Asset Storage volumes during local development you will need to fill in the Servd Project Slug and Servd Security Key settings. The values for these can be found in the Servd dashboard under Project Settings > Assets.
The plugin will automatically try to load these values from the environment variables `SERVD_PROJECT_SLUG` and `SERVD_SECURITY_KEY`, so you can simply add these two environment variables to your local dev environment to get things working.
Alternatively, you can add them directly to the plugin's settings in the Craft Control Panel in which case they will be added to your Craft Project Config files (so make sure they are kept secret!).
Servd Asset Volumes
Once the plugin is installed and configured you will be able to create 'Servd Asset Storage' volumes within the asset settings of Craft's Control Panel.
The default configuration for these volumes will work without any tweaks. You can test it out by uploading an image to your new volume and ensuring a thumbnail is generated and displayed.
Multiple Servd Volumes
You can create multiple Servd Asset Volumes within a single project to help keep things organised. However, if you do this you will need to supply a `subfolder` for each volume otherwise your files will all get mixed up and Craft's asset re-indexing will fail.
Environment Detection
The plugin will automatically separate your assets within the Servd Assets Platform depending on the environment that they were uploaded from. By default it will split your assets into the following:
local
staging
production
This ensures that changes you make to assets in one environment do not impact the assets in another.
If you connect to the Servd Asset Platform using an S3 client, you'll see these three directories in the root of your storage.
Using these standard environment names also allows Servd to include assets in any clone operations performed via the Servd dashboard. I.E. if you perform a full clone from staging -> production the platform is able to copy your assets from the staging directory, into the production directory.
Forcing a Specific Environment
If you wish to prevent the plugin from auto-detecting the current environment (so that you can E.G. interact with production assets whilst working locally) you can override the environment detection using the Assets Volume Environment setting in the main plugin settings. We advise that you set this to an environment variable so that you can tweak it dynamically as required.
How the Image Optimisation works
The Servd Plugin's image optimisation performs the following steps:
In your codebase, you generate a URL for an asset e.g. `myAsset.getUrl(...)`.
The plugin intercepts this request and returns a URL pointing to the Servd CDN with all of your transform options included. This URL is rendered in your HTML output.
The end user's browser then makes a request for this image URL. The Servd CDN checks for a cached copy of the transformed URL and returns it if it exists. If not, the request is passed along to a cloud function to perform the transformation.
The cloud function pulls in your original image, then uses SharpJS to apply the transforms which were encoded in the URL.
The resulting image is stored in a secondary cache before being sent back to the CDN to be delivered to the end user.
All of the above should happen automatically without requiring any input from your side - as long as the Servd Plugin is inserting the correct URLs into your HTML everything should happen automatically.
Disabling Servd Asset Platform Transforms and Optimisations
If you'd like to use Craft's default asset transform functionality, or you'd just like the Servd plugin to return links to all original uploaded assets instead of pre-optimised ones, you can disable all off server transforms and optimisations using the 'Disable Asset Platform image transforms / optimisations' switch in the plugin settings.
If this is switched on Servd Asset Volumes will begin acting just like standard S3 Asset Volumes - relying on GD, ImageMagick or another plugin to perform any required transformations.
This can also be useful if you're setting up a statically generated site and would like to process your images using a 3rd party platform.
Using a Custom Domain For Assets
The Custom CDN URL Pattern and Custom Image Optimise URL Pattern volume settings can be used to specify a custom domain name and URL pattern to use for optimised and unoptimised files. You can read more about how to set that up here.
Static Caching
Servd has a static caching solution which is available for all projects to make use of. This plugin provides deep integration with your project's static cache by allowing brute force or intelligent cache purges to occur. You can select when the cache is purged and what strategy is used to perform the purge within the plugin settings.
Trigger - None
The cache will never be automatically purged in any way.
Trigger - Only when entries are updated via the control panel
The cache will only be purged if a Craft Entry is updated from within the control panel. This prevents purges from occurring when an end-user submits a form from the front end or makes a Commerce purchase - both of which might edit an Entry, but not from the control panel.
Trigger - When entries are updated in any way
The cache will be purged whenever an Entry is saved, no matter where the request originated from.
Strategy - Full Purge
A full purge will destroy the entire static cache immediately whenever a 'live' Craft Element is updated (not disabled or a draft). This is a brute force approach, but it ensures that any changes you have made are displayed on the front end immediately with no chance of any cached pages pages surviving.
Strategy - Automated Tag Based Purge
This purge mechanism tracks all of the Craft Elements which are loaded in order to render each URL on your site. These Element -> URL associations are stored within an efficient data structure for later retrieval.
When any 'live' Craft Element is updated, the plugin is able to determine which URLs need to be purged based on the Element -> URL associations and only these URLs are purged. This prevents sudden surges of traffic from reaching PHP due to a full cache purge, but relies on a relatively complex tagging system on the back end which might, in some edge case circumstances, result in some URLs being missed from purges.
Manual Cache Purges
As well as the built-in automatic cache purging mechanisms, the plugin also provides several ways to manually purge cached URLs:
On the Utilities > Clear Caches page in the Craft Control Panel, you have the option to fully purge the static cache by checking the Servd Static Cache check box.
On the edit page for any Craft Entry which has an associated URL, you will find buttons which allow you to purge the Entry's cache specifically, or purge any URLs which are associated with the Entry.
Use the Craft CLI command `./craft clear-caches/servd-static-cache`
CSRF Token Injection
By default Craft uses CSRF tokens within <form> elements. Static caching breaks this functionality by serving incorrect tokens to the majority of users. In order to prevent this you can enable CSRF token injection in the Servd Plugin settings. This will inject a small piece of javascript into all of your templated pages which checks for any CSRF tokens and replaces them with an uncached value.
Dynamic Content
Sometimes it's useful to be able to have specific sections of a page dynamic whilst keeping the majority of the page cached. The plugin contains a twig tag which can do this on your behalf:
{% dynamicInclude 'snippets/login' with {key: 'val'} only %}
The tag matches the syntax of the standard twig `{% include %}` tag exactly, so you can easily switch between standard and dynamic template includes.
This mechanism relies on Craft's action URL prefix being excluded from the static cache. Servd has this in place by default, but you might need to update it if you use a non-standard action URL prefix.
Dynamic Content Context
As with the normal `{% include %}` tag, the vast majority of the parent template's context will be made available to the dynamically loaded template by default. You can prevent the full context from being used by specifying the `only` flag.
Because the dynamic content is loaded in after the main page content using an ajax request, accessing `craft.app.request` from within the dynamically included template will return a different request than the one used to load the main page. If you need the dynamic content to be aware of the current URL, or its parent page, pass this information through to the include as additional context variables.
Due to the way the dynamic loading works, any simple data types (strings, numbers, arrays etc) in the parent context will be exposed publicly. This does not include any of Craft's global twig variables however. If you have sensitive content in your template context, always use the `only` flag and define your child template's context explicitly.
Dynamic Content Placeholder
If you would like to include some placeholder content which will display while your dynamic content is being loaded, you can add the `placeholder` flag. This flag must be the last one on the tag.
Once this has been added, a closing tag is also required and any content between the two will be used as the placeholder content:
{% dynamicInclude 'snippets/login' with {key: 'val'} only placeholder %} #{{-- Placeholder content can go in here --}} Login! {% endDynamicInclude %}
The placeholder content will be contained within a single, unstyled `<div>` and will be removed automatically when the dynamic content is ready.
You can use this to easily include a loading graphic, a null state, or some default content for when the end-user has javascript disabled.
Dynamic Content ESI
If you have ESI enabled on Servd, the plugin will automatically detect this and switch `{% dynamicInclude %}`s to use ESI instead of ajax requests, resulting in extremely quick page load times. No changes are required to your codebase. The implementation of ESI inclusion using this tag is... interesting, and relies on javascript being enabled on the client. If you're interested in why that's the case, we're always happy to talk tech.
Local Development Tooling
The plugin contains several features which aim to make local development a smoother process and save you time.
Force Local Volumes for Assets
You can force the use of local volumes when working outside of Servd to make development work a little quicker. To do so, just flip the Use Local Volumes During Dev switch in the plugin settings. This will convert all Servd Asset Volumes into Local Volumes during local dev, but keep them unchanged when running inside Servd itself. This setting also ensures that the Local Volume override does not leak into any Project Config files or database data which might inadvertently break the staging or production environment.
This setting is very useful if you have multiple developers working on a single project and they all need to keep track of their own sets of assets. It also ensures that assets used during local development do not count towards your Servd Asset Platform usage total.
This setting ignores the Assets Volume Environment setting (see Forcing a Specific Environment above) and will be applied regardless of any value added there.
Sync Assets
You can sync your assets from local to staging/production, or from staging/production to local. If you are using remote storage during local development (the default) this will simply trigger a clone task to copy the asset files between directories in the Servd Asset Platform. If you have Use Local Volumes During Dev enabled this will sync assets between your local filesystem and the specified remote storage directory.
You can trigger asset syncs using the following commands:
./craft servd-asset-storage/local/pull-assets./craft servd-asset-storage/local/push-assets
These commands will try their best to auto-detect all of the settings they need, even before the plugin has been fully configured within Craft. If it cannot identify specific settings it will prompt you for them, or you can supply them via CLI flags:
./craft servd-asset-storage/local/pull-assets --from=staging --servdSlug=my-project-slug --servdKey=my-servd-key --interactive=0./craft servd-asset-storage/local/push-assets --to=production --servdSlug=my-project-slug --servdKey=my-servd-key --interactive=0
Pull/Push Local Database
You can pull down a database from Servd or push up your local database at any time using the commands:
./craft servd-asset-storage/local/pull-database./craft servd-asset-storage/local/push-database
These commands will try their best to auto-detect all of the settings they need, even before Craft has been installed. If it cannot identify specific settings it will prompt you for them, or you can supply them via CLI flags:
./craft servd-asset-storage/local/pull-database --from=staging --servdSlug=my-project-slug --servdKey=my-servd-key --skipBackup=1 --interactive=0./craft servd-asset-storage/local/push-database --to=production --servdSlug=my-project-slug --servdKey=my-servd-key --interactive=0
Please note that while a database is being pushed to a Servd, the target environment is likely to become unresponsive
Integration with Imager-X
The plugin contains storage and transform adapters for ImagerX. These allow you to use the ImagerX template syntax whilst utilising Servd's Asset Platform for storage, optimisation and transformation of your images.
View our Imager X Integration doc page for more information.
Integration with ImageOptimize
The plugin contains a transform adaptor for the craft-imageoptimize plugin. Simply select 'Servd' as the active transformer in ImageOptimize's settings and ensure it isn't being overridden by an imageoptimize.php config file.
If you'd like to pre-generate resized images (not really necessary and can slow down the Craft CP) add the ImageOptimize Optimized Images Field to the Servd Asset Volume's fieldset.
Integration with Feedme
By default, the Feedme plugin will only write logs directly to the filesystem. This can be problematic when using a load balanced instances or when running on ephemeral filesystems, both of which are the case with Servd. In order to ensure you still have easy access to your Feedme logs the Servd Plugin has the ability to force Feedme to also write its logs to the standard log output, where Servd can collect them and display them in the Servd dashboard.
You can enable this functionality by flipping the `Send feedme logs to Craft's standard log output` switch in the Servd plugin's settings.