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

Optimization: Images Processing #1128

Closed
8 tasks done
robertu7 opened this issue Jun 1, 2020 · 6 comments
Closed
8 tasks done

Optimization: Images Processing #1128

robertu7 opened this issue Jun 1, 2020 · 6 comments
Labels
enhancement New feature or request

Comments

@robertu7
Copy link
Contributor

robertu7 commented Jun 1, 2020

Background

We have lots of images uploaded by users: avatars, profile covers, article embedded images, and etc. Based on Lighthouse Report, images have big negative impact for performance score:

image

In general, there are three sides to be optimzed:

Source

  • Compressing
  • Resizing: different sizes fit different needs
  • Formats: WebP, JPEG 2000, etc.
  • Progressive

Application

Proxy

Solutions

Currently, we will do simple image processing (compressing & resizing) in connectors/aws, while image uploading. But there are cons:

  1. It's synchronous, uploading is blocked by processing;
  2. Growing complexity, we need add more and more codes for above needs;

Lambda To Rescue!

With AWS Lambda, processing image will be asynchronously and separately. There are two ways to implement:

1) Lazy processing

Use Serverless Image Handler, process image on client requests, and cached by CDN.

Pro & Cons:

  • Lower S3 cost, only store raw images;
  • Higher CDN cost by low hit rate;
  • Longer response time, process on-demand;

2) Post-processing

  1. The client calls the API to upload image, server forward it to AWS S3 directly, now raw image is accessible.
  2. AWS Lambda post-process the raw image from AWS S3, asynchronously, now optimized images are accessible.

Steps

  1. Formating: WebP
  2. Resizing
    • avatar: raw, 144w
    • embed raw, 1080w, 540w, 360w, 144w
    • profileCover: raw, 1080w, 540w
  3. Compressing

Results

# AWS S3 
/matters-server-stage
├── 1080w
│   ├── uuid.jpeg
│   └── uuid.webp
├── 540w
│   ├── uuid.jpeg
│   └── uuid.webp
├── 360w
│   ├── uuid.jpeg
│   └── uuid.webp
├── 144w
│   ├── uuid.jpeg
│   └── uuid.webp
└── uuid.jpeg

Usage

<!-- <ArticleDetail.Content> -->
<figure>
  <picture>
    <source type="image/webp" media="(min-width: 768px)" srcset="https://xxx.cloudfront.net/embed/1080w/uuid.webp" alt="...">
    <source type="image/webp" srcset="https://xxx.cloudfront.net/embed/540w/uuid.webp" alt="...">
    <source media="(min-width: 768px)" srcset="https://xxx.cloudfront.net/embed/1080w/uuid.jpeg" alt="...">
    <img src="https://xxx.cloudfront.net/embed/540w/uuid.jpeg" alt="...">
  </picture>
  <figcaption>...</figcaption>
</figure>

<!-- <ArticleDigest.Cover>, View Mode = default -->
<picture>
  <source type="image/webp" media="(min-width: 768px)" srcset="https://xxx.cloudfront.net/embed/1080w/uuid.webp" alt="...">
  <source type="image/webp" srcset="https://xxx.cloudfront.net/embed/540w/uuid.webp" alt="...">
  <source media="(min-width: 768px)" srcset="https://xxx.cloudfront.net/embed/1080w/uuid.jpeg" alt="...">
  <img src="https://xxx.cloudfront.net/embed/540w/uuid.jpeg" alt="...">
</picture>

<!-- <ArticleDigest.Cover>, View Mode = compact -->
<picture>
  <source type="image/webp" media="(min-width: 768px)" srcset="https://xxx.cloudfront.net/embed/360w/uuid.webp" alt="...">
  <source type="image/webp" srcset="https://xxx.cloudfront.net/embed/144w/uuid.webp" alt="...">
  <source media="(min-width: 768px)" srcset="https://xxx.cloudfront.net/embed/360w/uuid.jpeg" alt="...">
  <img src="https://xxx.cloudfront.net/embed/144w/uuid.jpeg" alt="...">
</picture>

<!-- <UserProfile.Cover> -->
<picture>
  <source type="image/webp" media="(min-width: 768px)" srcset="https://xxx.cloudfront.net/profileCover/1080w/uuid.webp" alt="...">
  <source type="image/webp" srcset="https://xxx.cloudfront.net/profileCover/540w/uuid.webp" alt="...">
  <source media="(min-width: 768px)" srcset="https://xxx.cloudfront.net/profileCover/1080w/uuid.jpeg" alt="...">
  <img src="https://xxx.cloudfront.net/profileCover/540w/uuid.jpeg" alt="...">
</picture>

<!-- <Avatar> -->
<picture>
  <source type="image/webp" srcset="https://xxx.cloudfront.net/avatar/144w/uuid.webp" alt="...">
  <img src="https://xxx.cloudfront.net/profileCover/144w/uuid.jpeg" alt="...">
</picture>

[1] We do had set a long cache TTL in CloudFront, but LightHouse doesn't think so.
[2] https://css-tricks.com/responsive-images-css/
[3] https://dev.to/jsco/a-comprehensive-guide-to-responsive-images-picture-srcset-source-etc-4adj
[4] https://css-tricks.com/using-webp-images/#article-header-id-3

@robertu7 robertu7 added the enhancement New feature or request label Jun 1, 2020
@robertu7 robertu7 changed the title Optimization: Processing User Uploaded Images Optimization: Images Processing Jun 1, 2020
@guoliu
Copy link
Contributor

guoliu commented Jun 1, 2020

Great summary! One question I have in mind is, what do we display in editor after user upload image? Do we need to wait for image process to insert the image path, or should we get some placeholder first and replace it later?

@robertu7
Copy link
Contributor Author

robertu7 commented Jun 2, 2020

@robertu7
Copy link
Contributor Author

robertu7 commented Jun 2, 2020

@robertu7
Copy link
Contributor Author

@robertu7
Copy link
Contributor Author

robertu7 commented Jun 15, 2020

@robertu7
Copy link
Contributor Author

robertu7 commented Jun 22, 2020

@robertu7 robertu7 closed this as completed Aug 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants