or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

gatsby-integration.mdimage-analysis-utilities.mdimage-data-generation.mdimage-processing.mdindex.mdlegacy-responsive-images.mdplugin-configuration.md
tile.json

gatsby-integration.mddocs/

Gatsby Integration

Gatsby plugin lifecycle hooks and development server integration for seamless image processing within Gatsby's build pipeline.

Capabilities

Plugin Lifecycle Hooks

Gatsby plugin lifecycle functions that integrate image processing with Gatsby's build process.

/**
 * Sets up lazy image processing in development server
 * @param options - Gatsby lifecycle options
 * @param options.app - Express application instance
 * @param options.cache - Gatsby cache instance
 * @param options.reporter - Gatsby reporter instance
 * @returns Promise that resolves when setup is complete
 */
function onCreateDevServer(options: {
  app: Express.Application;
  cache: GatsbyCache;
  reporter: Reporter;
}): Promise<void>;

/**
 * Processes remaining image jobs after bootstrap
 * @param options - Gatsby lifecycle options
 * @param options.reporter - Gatsby reporter instance
 * @param options.cache - Gatsby cache instance
 * @param options.store - Gatsby store instance
 * @returns Promise that resolves when processing is complete
 */
function onPostBootstrap(options: {
  reporter: Reporter;
  cache: GatsbyCache;
  store: GatsbyStore;
}): Promise<void>;

/**
 * Initializes plugin in worker processes
 * @param options - Gatsby lifecycle options
 * @param options.actions - Gatsby actions object
 * @param pluginOptions - Plugin configuration options
 * @returns Promise that resolves when initialization is complete
 */
function onPluginInit(
  options: { actions: Actions },
  pluginOptions: ISharpPluginOptions
): Promise<void>;

/**
 * Sets up plugin before Gatsby bootstrap
 * @param options - Gatsby lifecycle options
 * @param options.actions - Gatsby actions object
 * @param options.emitter - Event emitter instance
 * @param options.cache - Gatsby cache instance
 * @param pluginOptions - Plugin configuration options
 * @returns Promise that resolves when setup is complete
 */
function onPreBootstrap(
  options: {
    actions: Actions;
    emitter: EventEmitter;
    cache: GatsbyCache;
  },
  pluginOptions: ISharpPluginOptions
): Promise<void>;

Usage in gatsby-node.js:

// These hooks are automatically called by Gatsby
// This is how the plugin integrates with Gatsby's lifecycle

exports.onPreBootstrap = async ({ actions, emitter, cache }, pluginOptions) => {
  // Plugin initialization
  console.log("Initializing gatsby-plugin-sharp...");
};

exports.onPluginInit = async ({ actions }, pluginOptions) => {
  // Worker initialization
  console.log("Initializing plugin in worker...");
};

exports.onCreateDevServer = async ({ app, cache, reporter }) => {
  // Development server setup
  console.log("Setting up lazy image processing...");
};

exports.onPostBootstrap = async ({ reporter, cache, store }) => {
  // Process remaining jobs
  console.log("Processing remaining image jobs...");
};

Plugin Options Schema

Joi validation schema for plugin configuration options.

/**
 * Defines Joi validation schema for plugin options
 * @param options - Joi schema builder options
 * @param options.Joi - Joi validation library instance
 * @returns Joi schema object for plugin options validation
 */
function pluginOptionsSchema({ Joi }: { Joi: any }): JoiSchema;

The schema validates the following options:

const optionsSchema = Joi.object({
  base64Width: Joi.number()
    .default(20)
    .description("The width of the generated base64 preview image"),
  
  forceBase64Format: Joi.any()
    .valid("png", "jpg", "webp")
    .description("Force a different format for the generated base64 image"),
  
  useMozJpeg: Joi.boolean()
    .description("Use the mozJpeg library for encoding"),
  
  stripMetadata: Joi.boolean().default(true),
  
  defaultQuality: Joi.number().default(50),
  
  failOnError: Joi.boolean().default(true), // Deprecated
  
  failOn: Joi.any()
    .valid("none", "truncated", "error", "warning")
    .default("warning")
    .description("Level of sensitivity to invalid images"),
  
  defaults: Joi.object({
    formats: Joi.array().items(
      Joi.string().valid("auto", "png", "jpg", "webp", "avif")
    ),
    placeholder: Joi.string().valid(
      "tracedSVG", "dominantColor", "blurred", "none"
    ),
    quality: Joi.number(),
    breakpoints: Joi.array().items(Joi.number()),
    backgroundColor: Joi.string(),
    transformOptions: Joi.object(),
    tracedSVGOptions: Joi.object(),
    blurredOptions: Joi.object(),
    jpgOptions: Joi.object(),
    pngOptions: Joi.object(),
    webpOptions: Joi.object(),
    avifOptions: Joi.object(),
  }).description("Default options used by gatsby-plugin-image")
});

Development Server Integration

Lazy Image Processing

In development mode, the plugin sets up lazy image processing to improve build performance:

// Middleware for handling lazy image requests
app.use(async (req, res, next) => {
  const decodedURI = decodeURIComponent(req.path);
  const pathOnDisk = path.resolve(path.join("./public/", decodedURI));
  
  // Check if this is a lazy image request
  const jobContentDigest = await cache.get(decodedURI);
  const cacheResult = jobContentDigest ? await cache.get(jobContentDigest) : null;
  
  if (cacheResult) {
    // Process the image on-demand
    await processLazyImage(cacheResult, pathOnDisk, reporter);
    return res.sendFile(pathOnDisk);
  }
  
  next();
});

Job Management

The plugin integrates with Gatsby's job system for efficient image processing:

/**
 * Internal job creation function (unstable API)
 * @param job - Job configuration object
 * @param options - Job options including reporter
 * @returns Promise that resolves when job is created
 */
function _unstable_createJob(job: JobConfig, options: { reporter: Reporter }): Promise<void>;

/**
 * Internal function to check if lazy job processing is enabled
 * @returns Boolean indicating if lazy jobs are enabled
 */
function _lazyJobsEnabled(): boolean;

interface JobConfig {
  name: string;           // Job name identifier
  inputPaths: string[];   // Input file paths
  outputDir: string;      // Output directory
  args: {
    isLazy: boolean;      // Whether job should be processed lazily
    operations: Array<{   // Processing operations
      outputPath: string;
      args: ITransformArgs;
    }>;
    pluginOptions: ISharpPluginOptions;
  };
}

Worker Processing

Image Processing Worker

The plugin uses Gatsby's worker system for concurrent image processing:

/**
 * Worker function for processing image transformation jobs
 * @param options - Worker job options
 * @param options.inputPaths - Array of input file paths
 * @param options.outputDir - Output directory for processed images
 * @param options.args - Processing arguments and operations
 * @returns Promise that resolves when processing is complete
 */
function IMAGE_PROCESSING(options: {
  inputPaths: Array<{ path: string }>;
  outputDir: string;
  args: {
    isLazy: boolean;
    operations: Array<{
      outputPath: string;
      args: ITransformArgs;
    }>;
    pluginOptions: ISharpPluginOptions;
  };
}): Promise<void>;

/**
 * Job name identifier for image processing jobs
 */
const IMAGE_PROCESSING_JOB_NAME = "IMAGE_PROCESSING";

Concurrency Management

// Worker queue configuration
const queue = require("async/queue");
const { cpuCoreCount } = require("gatsby-core-utils/cpu-core-count");

const concurrency = process.env.GATSBY_WORKER_POOL_WORKER
  ? 1  // Single core in worker processes
  : Math.max(1, cpuCoreCount() - 1); // Multi-core in main process

Integration Examples

Custom GraphQL Resolver

// gatsby-node.js - Custom image processing resolver
exports.createResolvers = ({ createResolvers }) => {
  const resolvers = {
    File: {
      customImageProcessing: {
        type: "JSON",
        async resolve(source, args, context) {
          const { queueImageResizing } = require("gatsby-plugin-sharp");
          
          return await queueImageResizing({
            file: source,
            args: {
              width: args.width,
              height: args.height,
              quality: args.quality || 80
            },
            reporter: context.reporter
          });
        }
      }
    }
  };
  
  createResolvers(resolvers);
};

Build-Time Image Processing

// gatsby-node.js - Process images during build
exports.onCreateNode = async ({ node, actions, reporter, cache }) => {
  const { createNode } = actions;
  
  if (node.internal.type === "File" && node.extension === "jpg") {
    const { generateImageData } = require("gatsby-plugin-sharp");
    
    const imageData = await generateImageData({
      file: node,
      args: {
        layout: "constrained",
        width: 800,
        formats: ["auto", "webp"]
      },
      pathPrefix: "/",
      reporter,
      cache
    });
    
    if (imageData) {
      createNode({
        ...imageData,
        id: `${node.id}-processed`,
        parent: node.id,
        internal: {
          type: "ProcessedImage",
          contentDigest: node.internal.contentDigest
        }
      });
    }
  }
};

Plugin Extension

// Creating a custom plugin that extends gatsby-plugin-sharp
const { setActions } = require("gatsby-plugin-sharp");

exports.onPreBootstrap = ({ actions }) => {
  // Initialize gatsby-plugin-sharp actions
  setActions(actions);
};

exports.createResolvers = ({ createResolvers }) => {
  const resolvers = {
    File: {
      watermarkedImage: {
        type: "JSON",
        async resolve(source, args, context) {
          const { queueImageResizing } = require("gatsby-plugin-sharp");
          
          // Custom watermarking logic
          return await queueImageResizing({
            file: source,
            args: {
              width: args.width,
              quality: 85,
              // Custom watermark processing would go here
            },
            reporter: context.reporter
          });
        }
      }
    }
  };
  
  createResolvers(resolvers);
};

Error Handling and Debugging

Error Reporting

The plugin integrates with Gatsby's error reporting system:

const { reportError } = require("gatsby-plugin-sharp/src/report-error");

// Report processing errors
try {
  await processImage(file);
} catch (error) {
  reportError("Failed to process image", error, reporter);
}

Development Debugging

// Enable debug logging
const debug = require("debug")("gatsby:gatsby-plugin-sharp");

debug("Processing image:", file.absolutePath);
debug("Transform args:", args);

Performance Monitoring

// Monitor job completion
emitter.on("END_JOB_V2", action => {
  if (action.plugin.name === "gatsby-plugin-sharp") {
    console.log(`Completed image processing job: ${action.payload.jobContentDigest}`);
  }
});

Configuration Best Practices

Production Configuration

// gatsby-config.js - Production optimized
module.exports = {
  plugins: [
    {
      resolve: "gatsby-plugin-sharp",
      options: {
        defaultQuality: 85,
        stripMetadata: true,
        useMozJpeg: true,
        failOn: "error",
        defaults: {
          formats: ["auto", "webp", "avif"],
          placeholder: "blurred",
          quality: 90
        }
      }
    }
  ]
};

Development Configuration

// gatsby-config.js - Development optimized
module.exports = {
  plugins: [
    {
      resolve: "gatsby-plugin-sharp",
      options: {
        defaultQuality: 60, // Lower quality for faster builds
        stripMetadata: false, // Keep metadata for debugging
        failOn: "warning", // More lenient error handling
        defaults: {
          formats: ["auto"], // Fewer formats for speed
          placeholder: "dominantColor" // Faster placeholder generation
        }
      }
    }
  ]
};