1.1.0 • Published 5 months ago

@danielbiegler/vendure-plugin-blurry-image-lazy-loading v1.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
5 months ago

Banner Image

Vendure Plugin: Blurry Image Lazy Loading

Generates image hashes for displaying blurry previews when loading images on the frontend.

Features

  • CustomField on Asset Entities containing a hash for your frontend.
  • Automatic creation of hashes for new assets via event bus.
  • Synchronous creation of hashes for direct consumption.
  • Asynchronous creation of hashes via dedicated job queue.
  • Out of the box comes with two different hashing strategies and can be extended if need be via a custom PreviewImageHashStrategy.
  • Suite of end-to-end tests ensuring correctness.

End-To-End Tests

 ✓ blurry-image-lazy-loading/e2e/thumbhash.e2e-spec.ts (8 tests)
 ✓ blurry-image-lazy-loading/e2e/blurhash.e2e-spec.ts (8 tests)
 ✓ blurry-image-lazy-loading/e2e/common.e2e-spec.ts (14 tests)

 Test Files  3 passed (3)
      Tests  30 passed (30)

Example comparisons

The ThumbHash Website has an interactive online comparison generator.

size-comparison-banner.png

size-comparison-camera.png

size-comparison-lipstick.png

size-comparison-opera.png

How To: Usage

The plugin adds a couple ways to generate hashes for you to the admin api endpoint. Your admin-client needs the CreateAsset Vendure permission in order to call the following mutations. See resolver.

extend type Mutation {
  """
  Create a preview image hash for one image.
  """
  pluginPreviewImageHashCreateImageHash(
    input: PluginPreviewImageHashCreateInput!
  ): PluginPreviewImageHashCreateResult!

  """
  Create preview image hashes for a product.
  This includes both the product itself and all of its ProductVariant assets.
  """
  pluginPreviewImageHashCreateImageHashesForProduct(
    input: PluginPreviewImageHashForProductInput!
  ): PluginPreviewImageHashResult!

  """
  Create preview image hashes for an entire collection.
  This includes the collection, the contained Product-assets and related ProductVariant-assets.

  Due to how large collections can become, you may want to disable the deduplication of asset ids.
  If deduplication is enabled, jobs will be created only after gathering all assets first.
  If disabled, jobs will be created as the assets are being read.

  No deduplication may result in assets being hashed multiple times, but the tradeoff is not having
  to hold potentially millions of records in memory and just letting the worker take care of them eventually.
  """
  pluginPreviewImageHashCreateImageHashesForCollection(
    input: PluginPreviewImageHashForCollectionInput!
  ): PluginPreviewImageHashResult!

  """
  Create preview image hashes for all assets.
  
  This mutation should be handled with extra care since an installation may hold hundreds of thousands of images.
  This is mainly useful as a one-time-use utility to initialize all of the assets with hashes after installing the plugin.
  """
  pluginPreviewImageHashCreateImageHashesForAllAssets(
    input: PluginPreviewImageHashForAllAssetsInput
  ): PluginPreviewImageHashResult!
}

See api-extensions.ts for a complete overview of the graphql extensions and types.

1. Add the plugin to your Vendure Config

You can find the package over on npm and install it via:

npm i @danielbiegler/vendure-plugin-blurry-image-lazy-loading

The simplest way is relying on the defaults and just adding the plugin with a hashing strategy.

import { PreviewImageHashPlugin, ThumbHashStrategy } from "@danielbiegler/vendure-plugin-blurry-image-lazy-loading";
export const config: VendureConfig = {
  // ...
  plugins: [
    PreviewImageHashPlugin.init({
      hashingStrategy: new ThumbHashStrategy(), // Recommended
    }),
  ],
}

It's possible to pass in further configurations into both the plugin and the strategies, for example:

PreviewImageHashPlugin.init({
  enqueueHashingAfterAssetCreation: false,
  hashingStrategy: new ThumbHashStrategy({
    encoding: "hex",
    resizeOptions: {
      width: 32,
      fit: "contain"
    }
  }),
})

Please refer to the specific docs for how and what you can customize.

2. Generate a database migration

This plugin adds a custom field to the Asset entity called previewImageHash, which requires you to generate a database migration. See Vendure's migration documentation for further guidance.

3. Generate hashes

By default the option enqueueHashingAfterAssetCreation automatically adds hashing tasks to the dedicated job queue for newly added assets.

For existing assets you can produce hashes either synchronously or via the job queue, of which the latter is recommended for production environments, via the admin API:

mutation {
  pluginPreviewImageHashCreateImageHash(
    input: {
      idAsset: "example123",
      runSynchronously: true,  # False by default
    }
  ) {
    # When running asynchronously you get a short status response.
    ... on PluginPreviewImageHashResult {
      code
      jobsAddedToQueue
      assetsSkipped
      message
    }

    # When running synchronously, you get the Asset directly.
    # This is useful for scripts.
    ... on Asset {
      id
      name
      customFields {
        previewImageHash
      }
    }
  }
}

4. Consume the hashes in your frontend

Now that your assets have hashes you may consume them on your frontend. How and where you consume them exactly is dependent on your setup, but in general it involves the following steps.

  1. Retrieve assets, for example:
query {
  collection(slug: "example") {
    productVariants(options: { take: 10 }) {
      items {
        name
        featuredAsset {
          preview
          width
          height
          customFields {
            previewImageHash
          }
        }
      }
    }
  }
}
  1. For example with the ThumbHashStrategy and its BufferEncoding set to the default "base64" you can now decode the hashes with the provided helper like so:

// Node
const buffer = Buffer.from(previewImagehash, "base64");
const dataUrl = thumbHashToDataURL(buffer);
// Browser
// Warning: `atob` can throw! You should make a proper helper method with error handling. Skipping that here for brevity.
const buffer = Uint8Array.from(atob(previewImagehash), (v) => v.charCodeAt(0));
const dataUrl = thumbHashToDataURL(buffer);
  1. Use the result in your frontend. There are some environment specific implementation details, so we'll use an imaginary react component here for brevity.
<MyCustomImgComponent
  previewSrc={dataUrl}
  src={asset.preview}
  width={asset.width}
  height={asset.height}
/>

Credits

1.1.0

5 months ago

1.0.1

7 months ago

1.0.0

7 months ago

0.1.3

7 months ago

0.1.2

7 months ago

0.1.1

7 months ago

0.1.0

7 months ago