feat: optimize mockup images with WebP and auto-regeneration
Convert mockup source images from JPG to WebP format for 76% size reduction (20MB → 4.7MB). Variants are now auto-generated on startup via Oban, keeping the same DRY approach as database images. Changes: - Add OptimizeWorker.enqueue_mockup/1 for filesystem images - Extend VariantCache to check mockup sources on startup - Update MockupGenerator to save source as optimized WebP - Update .gitignore to ignore generated variants - Convert 55 source mockups from JPG to WebP The mockup pipeline now uses the same code paths as database images: - Optimizer.to_optimized_webp/1 for source conversion - Optimizer.process_file/3 for variant generation - OptimizeWorker for Oban background processing - VariantCache for startup cache validation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -328,20 +328,35 @@ defmodule SimpleshopTheme.Printify.MockupGenerator do
|
||||
end
|
||||
|
||||
@doc """
|
||||
Download mockup images to the output directory.
|
||||
Download mockup images, save as WebP source, and generate variants.
|
||||
Sources are saved for regeneration on startup via VariantCache.
|
||||
"""
|
||||
def download_mockups(product_slug, mockup_urls) do
|
||||
alias SimpleshopTheme.Images.Optimizer
|
||||
|
||||
File.mkdir_p!(@output_dir)
|
||||
|
||||
mockup_urls
|
||||
|> Enum.with_index(1)
|
||||
|> Enum.map(fn {url, index} ->
|
||||
output_path = Path.join(@output_dir, "#{product_slug}-#{index}.jpg")
|
||||
IO.puts(" Downloading mockup #{index} to #{output_path}...")
|
||||
basename = "#{product_slug}-#{index}"
|
||||
source_path = Path.join(@output_dir, "#{basename}.webp")
|
||||
IO.puts(" Processing mockup #{index}...")
|
||||
|
||||
case Client.download_file(url, output_path) do
|
||||
{:ok, path} -> {:ok, path}
|
||||
{:error, reason} -> {:error, {url, reason}}
|
||||
temp_path = Path.join(System.tmp_dir!(), "#{basename}-temp.jpg")
|
||||
|
||||
with {:ok, _} <- Client.download_file(url, temp_path),
|
||||
{:ok, image_data} <- File.read(temp_path),
|
||||
{:ok, webp_data, source_width, _} <- Optimizer.to_optimized_webp(image_data),
|
||||
:ok <- File.write(source_path, webp_data),
|
||||
{:ok, _} <- Optimizer.process_file(webp_data, basename, @output_dir) do
|
||||
File.rm(temp_path)
|
||||
IO.puts(" Saved source + variants for #{basename} (#{source_width}px)")
|
||||
{:ok, basename, source_width}
|
||||
else
|
||||
{:error, reason} ->
|
||||
File.rm(temp_path)
|
||||
{:error, {url, reason}}
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user