Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parcel 2: HTML Image Transformer #3738

Open
devongovett opened this issue Nov 3, 2019 · 7 comments
Open

Parcel 2: HTML Image Transformer #3738

devongovett opened this issue Nov 3, 2019 · 7 comments

Comments

@devongovett
Copy link
Member

Create the @parcel/transformer-html-images (name TBD) package. This should include a Transformer plugin that transforms <img> tags in HTML to <picture> elements with multiple sources. It should work with the @parcel/transformer-webp and @parcel/transformer-image-resize plugins to create multiple dependencies that are transformed by those plugins and re-inserted later as URLs. This handles generating multiple versions of an image with different sizes and formats from a source HTML file and image completely automatically.

HTML like this:

<img src="./image.jpg" width="200">

should be transformed into HTML like this, with dependencies created for each referenced asset:

<picture>
  <source type="image/webp" srcset="webp:./image.jpg?width=200, webp:./image.jpg?width=400 2x">
  <source type="image/jpeg" srcset="./image.jpg?width=200, ./image.jpg?width=400 2x">
  <img src="./image.jpg?width=200" width="200">
</picture>

This automatically handles creating both WebP and JPG versions of the image, at multiple resolutions.

In addition, the srcset attribute should be supported to generate multiple versions with specific sizes from the same input image:

<img srcset="image.jpg 480w, image.jpg 1080w">

becomes:

<picture>
  <source type="image/webp" srcset="webp:image.jpg?width=480 480w, webp:image.jpg?width=1080 1080w">
  <source type="image/jpeg" srcset="image.jpg?width=480 480w image.jpg?width=1080 1080w">
  <img src="./image.jpg?width=1080w">
</picture>

Note that the protocol and query param syntax here is internal to Parcel and would not be shipped to users. After the images are transformed, the final URL would be placed into the HTML file as expected.

Open Questions

  • What should the default resolutions include? 1x, 2x, 3x? Should this happen by default at all or should we require users specify srcset in their code themselves? Seems like it should be fairly common to want this...
  • What should the default formats include? WebP and the original format? WebP and JPEG always?
  • What should happen if there is no width or height set on an <img>? Just convert to WebP without resizing?
@mischnic
Copy link
Member

mischnic commented Nov 4, 2019

width and height will be used to calculate the aspect ratio which can reduce layout jank, so we should consider adding these attributes (automatically? - does that have layout sideeffects?):
https://twitter.com/addyosmani/status/1169813271009886208

@kevincox
Copy link
Contributor

I wouldn't want this to be specific to HTML. I have a lot of my source images as SVG but sometimes need/want them rendered into other formats. For example:

  • Background images for CSS.
  • Icons for a Web App Manifest.
  • Image URLs used by javascript.
  • Favicons.

All of these would have a use for images rendered into select formats at different resolutions. Can we try to find a solution that works uniformly wherever images are needed?

@hsablonniere
Copy link

It would be great to have this 🙏

With my limited knowledge of Parcel, I see a Transformer reading HTML's AST from posthtml, transforming <img> nodes using JPEG images and replacing them with <picture> with WebP (AVIF maybe) alternatives.

Is this done with the MutableAsset.addDependency or even MutableAsset.addURLDependency?

We should warn users that the HTML structure will be modified so their CSS must be resilient to that.

@mischnic

This comment has been minimized.

@ivoba

This comment has been minimized.

@thewilkybarkid
Copy link
Contributor

We should warn users that the HTML structure will be modified so their CSS must be resilient to that.

Related to the discussion around #6783 (comment), the addition of <picture> can create CSS issues (e.g. a div > img selector will no longer work).

It would be safer to have it so

<img src="./image.jpg" width="200">

wouldn't create a <picture>, and so it can't have generated <source>s. It could, however, have an srcset added.

To have new <source>s, it would need to be:

<picture>
<img src="./image.jpg" width="200">
</picture>

@thewilkybarkid
Copy link
Contributor

thewilkybarkid commented Dec 1, 2021

  • What should the default resolutions include? 1x, 2x, 3x? Should this happen by default at all or should we require users specify srcset in their code themselves? Seems like it should be fairly common to want this...

1x and 2x is probably enough as a default (though I have found 2x images can still be fairly large and 1.5x can be a decent compromise).

  • What should the default formats include? WebP and the original format? WebP and JPEG always?

Reading https://www.smashingmagazine.com/2021/09/modern-image-formats-avif-webp/ and https://www.contentful.com/blog/2021/11/29/load-avif-webp-using-html/, I wonder if it should be like:

Input Sources
JPEG AVIF (lossy), WebP (lossy), JPEG
PNG WebP (lossless), PNG

There's never going to be a silver bullet for this though.

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

No branches or pull requests

6 participants