What, no images?

2022.03.15
Druxt

A picture is worth a thousand words, but how many lines of code does it take to add images to a serverless Druxt site?

A blog without images is hard, but is getting Drupal managed files from an un-hosted Drupal backend harder?

What's the problem with images?

Drupal is a very powerful open-source content management system, and over the years there has been a large emphasis on media management, because, really, it's quite rare to build a site, blog or web application without images.

But when launching this site, and building the Druxt serverless quickstart template, I had to make the decision to exclude images.

Why?

Because out of the box, Drupal media, and files, are served by Drupal. But the whole point of a serverless site is to not have a server, and no server means no images.

So, no images then?

Well, not exactly. Where there is a problem, there is inevitably a workaround, and ideally a solution. The workaround is relatively straight forward; have your images in the frontend, e.g., make your images part of the Nuxt theme components.

However, this only solves theme and layout images, and does nothing to solve the issue of content managed issues.

So what's the solution?

Experimenting with Cloudinary

My original thoughts, and the experiment I put the most time into; host the images on a third-party image service provider, like Cloudinary.

I specifically chose Cloudinary for a few reasons:

  1. There's a Drupal module: https://www.drupal.org/project/cloudinary
  2. There's a Nuxt Image module provider: https://image.nuxtjs.org/providers/cloudinary
  3. There's a free option, and serverless is all about hosting your Drupal content for free, where possible.

Unfortunately the Drupal module does not yet have a viable release for Drupal 9.

While there is an open merge request to add support, through testing I have determined that it is not yet ready for use.

Next? Nuxt (Image)!

While I was certain I had been on the right direction with Cloudinary, or more specifically, a CDN based image provide, I know I am on the right direction with the Nuxt Image module.

One of my original thoughts was that the Drupal file system could be symbolically linked into the Nuxt assets directory, or alternatively Nuxt could pull the images in from the Drupal backend during the Nuxt build/generate process.

Turns out the Nuxt Image module already has the ability built in, so no third-party image service provider is required at all.

The steps

There's not a lot involved to get it working, which is the best kind of solution.

Download the Nuxt Image module:

npm install --save-dev @nuxt/image

Add the module and configure it with your Drupal backend domain (baseUrl if you're using one of the Druxt quickstart templates):

nuxt.config.js
buildModules: [
  ['@nuxt/image', { domains: [baseUrl] }],
]

Add a DruxtFieldImage component to render the image using the NuxtImage component:

~/components/druxt/field/Image.vue
<template>
  <DruxtEntity type="file--file" :uuid="model.data.id">
    <template #default="{ entity }">
      <NuxtImg :src="src(entity)" />
    </template>
  </DruxtEntity>
</template>

<script>
import { DruxtFieldMixin } from 'druxt-entity'
export default {
  mixins: [DruxtFieldMixin],
  methods: {
    src(entity) {
      return [this.$druxt.settings.baseUrl, entity.attributes.uri.url].join('/')
    },
  },
}
</script>

The DruxtFieldImage component also converts the relative URL of the image to an absolute URL, which is required for the Nuxt Image module to do it's job.

And that's it, assuming everything was done correctly you are now able to run the nuxt generate command and it will process your Drupal hosted images into the your dist folder.

The end result

"No images" no more, and thankfully it was much easier than expected; I had been expecting to have to update the merge request for Cloudinary, which is not a small task and not something I was looking forward to.

The Nuxt Image module is fantastic, it does everything I needed, and more than I could have hoped for.

And of course, with a solution found I have also updated the Druxt Serverless Quickstart template so that next time I, or anyone else, wants a serverless Druxt site with the full power of Drupal Media it is ready to go out of the box.

One click, Fully Decoupled, Full Static, Serverless Drupal Site starter-kit with Druxt.

See the code Run in Gitpod