Skip to content

Add cwebp task for converting images to WebP format - #7690

Open
pbearne wants to merge 5 commits into
WordPress:trunkfrom
pbearne:62188-compress-webp-images-incore-and-core-themes
Open

pbearne wants to merge 5 commits into
WordPress:trunkfrom
pbearne:62188-compress-webp-images-incore-and-core-themes

Conversation

@pbearne

@pbearne pbearne commented Oct 30, 2024

Copy link
Copy Markdown

Implemented 'cwebp' Grunt task to convert images to WebP format. Updated 'precommit:image' task to include 'cwebp:dynamic' ensuring WebP conversion during pre-commit.

Trac ticket: https://core.trac.wordpress.org/ticket/62188

Implemented 'cwebp' Grunt task to convert images to WebP format. Updated 'precommit:image' task to include 'cwebp:dynamic' ensuring WebP conversion during pre-commit.
@github-actions

github-actions Bot commented Oct 30, 2024 •

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs.

Core Committers: Use this line as a base for the props when committing in SVN:

Props pbearne, mukesh27, adamsilverstein, lancewillett, desrosj.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.


Props Bot commands

You can trigger Props Bot actions by commenting on this PR:

  • @propsbot add <username> to give props to a GitHub user. Requires write access.
  • @propsbot remove <username> to leave a user out of the props. Requires write access.
  • @propsbot refresh to refresh this list. Adding the props-bot label works too.

@github-actions

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • The Plugin and Theme Directories cannot be accessed within Playground.
  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

Comment thread Gruntfile.js Resolved
@desrosj

desrosj commented Nov 6, 2024

Copy link
Copy Markdown
Member

I agree with the image quality likely being far too low. It seems Core uses 86 as the default for WebP. I think matching that is a good start.

Were there specific reasons for choosing grunt-cwebp over some of the other available options, such as Ayesh/grunt-webp? The former has not been updated in 4 years, but the latter was updated 2 years ago and @Ayesh is an active member of the community, so it may be easier to get any needed updates released.

There's also some additional options such as lossless, and deleteLarger in Ayesh/grunt-webp. I wonder if configuring these would be beneficial as well.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The WebP task uses glob patterns that match no files, writes output to a literal SOURCE_DIR/ directory, and is not triggered by WebP-only changes during pre-commit.

3 open issues
What changed in this PR

This PR adds WebP processing to WordPress’s Grunt-based image workflow and connects it to the image pre-commit task.

Changes:

  • Adds grunt-cwebp and its locked dependencies.
  • Configures a cwebp:dynamic target for core and theme WebP assets at quality 80.
  • Adds the target to precommit:image after image minification.
File Description
package.json Adds the grunt-cwebp development dependency.
package-lock.json Locks the new dependency tree and updates shared dependency metadata.
Gruntfile.js Configures WebP processing and includes it in the image pre-commit task.

Review effort: Balanced

Comment thread Gruntfile.js Resolved
Comment thread Gruntfile.js Resolved
Comment thread Gruntfile.js Resolved

@lancewillett lancewillett left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dest: 'SOURCE_DIR' is a literal directory name, rather than the configured source directory. Please correct the output mapping and verify the intended behavior on a second precommit:image run: the current inputs are already WebP files, so repeated lossy re-encoding needs to be avoided. The Grunt and package changes also need refreshing against trunk.

AI review · gpt-6

pbearne and others added 2 commits November 5, 2026 15:41
Updated glob patterns for webp images and fixed destination path.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The precommit image target repeatedly overwrites existing WebPs with lossy re-encodings, causing cumulative quality loss and unrelated asset changes even when only a PNG is edited.

No open issues 🎉

1 previously missed issue

In code that hasn't changed since last review

Medium severity Avoid cumulative lossy re-encoding of existing WebP assets

Gruntfile.js:1047

q: 80 performs lossy re-encoding, but this target reads existing WebP files and writes back to the same paths. Because precommit:image runs this target for any image change, even an unrelated PNG edit re-encodes all existing theme WebPs; subsequent runs use the previously compressed output, causing cumulative quality loss and unrelated asset changes. Please use lossless optimization for existing WebPs, or generate lossy outputs from preserved original sources instead of overwriting and reusing them.

3 resolved since last review

Review effort: Balanced

…themes

# Conflicts:
#	Gruntfile.js
#	package-lock.json
#	package.json
@pbearne
pbearne requested a review from lancewillett November 6, 2026 15:44

@lancewillett lancewillett left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for refreshing this. It's not ready yet:

  1. Every CI job fails at npm ci. package.json adds grunt-contrib-imagemin, which r63784 removed, while package-lock.json adds grunt-cwebp. The two files are out of sync ("Missing: grunt-contrib-imagemin@4.0.0 from lock file").
  2. The cwebp task never runs. precommit:image still lists only imagemin:core, though the PR description says it adds cwebp:dynamic. And since grunt-cwebp isn't in package.json, the loadNpmTasks loop never loads it.
  3. Adding webp to the precommit check runs imagemin:core, which only handles PNG, JPEG and GIF.
  4. Wired up, it would degrade the images. It re-encodes the existing .webp files in place at quality 80, so every run loses more quality. I raised this on Oct 31.

There's a simpler path now. r63784 replaced grunt-contrib-imagemin with a local task, tools/imagemin/task.js, built on @napi-rs/image. That library already has Transformer#webpLosslessSync(). Adding WebP to that task would keep the output lossless and reuse its 64-byte threshold to skip trivial rewrites. It also avoids a new dependency: grunt-cwebp was last published in 2022, and cwebp-bin runs an install script to fetch the binary. Would you be up for reworking it that way?

AI review · claude-opus-5-5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants