Skip to content
This repository has been archived by the owner on Aug 30, 2020. It is now read-only.

Commit

Permalink
feat: add image transformation
Browse files Browse the repository at this point in the history
feat: add empty lazy image

add lazy image

add lazy

add image ratio

feat: add empty lazy image

add lazy image

add lazy

add image ratio

Merge branch 'lazy-intersection' of github.com:josteph/tkpd-ta-web-vitals into lazy-intersection
* 'lazy-intersection' of github.com:josteph/tkpd-ta-web-vitals:
  add lazy image
  feat: add empty lazy image
  feat: add image transformation
  improvment: upload image to CDN
  improvement: manual resize image size
  improvement: set image height to improve CLS
  chore: add analyze script

feat: remove unused 3rd party lib

fix: remove unused wrapper

feat: use image object
  • Loading branch information
irfan-maulana-tkp committed Aug 10, 2020
1 parent 7370f2d commit ffff81b
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 16 deletions.
3 changes: 1 addition & 2 deletions client/components/Header/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react';
import logo from '../../assets/logo.svg';

const headerStyle = {
height: '65px',
Expand All @@ -19,7 +18,7 @@ const imageStyle = {
const Header = () => {
return (
<div className="header" style={headerStyle}>
<img src={logo} alt="logo" style={imageStyle} />
<svg style={imageStyle} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/></g></svg>
<h1>App Sample</h1>
</div>
);
Expand Down
58 changes: 58 additions & 0 deletions client/components/LazyImage/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React, { useState } from 'react';
import { string, object } from 'prop-types';
import useIntersect from '@jackyef/use-intersect';

const optionsData = {
root: null,
rootMargin: '0px',
threshold: [0, 0, 0, 0],
};

const LazyImage = ({ alt, src, style, width, height }) => {
const placeholder = `https://res.cloudinary.com/irfan-maulana-tkpd/image/fetch/c_fill,g_auto:face,h_50,fl_force_strip.progressive/f_webp/${encodeURIComponent(
'https://res.cloudinary.com/irfan-maulana-tkpd/image/upload/v1597041453/placeholder_qzxxc6.png',
)}`;

const [showSrc, setShowSrc] = useState(placeholder);
const [loaded, setLoaded] = useState(false);

const onIntersect = () => {
const imgObj = new Image();
imgObj.onload = () => {
setLoaded(true);
}
imgObj.src = src;
setShowSrc(src);
};

const targetRef = useIntersect(onIntersect, optionsData, true);

return (
<img
ref={targetRef}
alt={alt}
className={`img ${loaded ? 'img--loaded' : 'img--loading'}`}
style={style}
src={showSrc}
width={width}
height={height}
/>
);
};

LazyImage.propTypes = {
alt: string.isRequired,
height: string,
src: string,
style: object,
width: string,
};

LazyImage.defaultProps = {
height: undefined,
src: '',
style: {},
width: '100%',
};

export default LazyImage;
29 changes: 16 additions & 13 deletions client/routes/Home/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Link } from 'react-router-dom';

import Header from '../../../components/Header';
import RatingReview from '../../../components/RatingReview';
import LazyImage from '../../../components/LazyImage';
import Footer from '../../../components/Footer';

const productWrapper = {
Expand All @@ -21,15 +22,14 @@ const productCard = {
marginBottom: '10px',
boxShadow: '0 1px 6px 0 rgb(255 255 255 / 0.32)',
borderRadius: '8px',
textDecoration: 'none',
color: '#fff',
cursor: 'pointer',
textDecoration: 'none',
color: '#fff',
cursor: 'pointer',
};

const productImg = {
width: '100%',
height: '130px',
objectFit: 'cover',
borderRadius: '8px 8px 0 0',
};

Expand All @@ -43,8 +43,8 @@ const productName = {
};

const productPrice = {
color: '#ff5722',
fontSize: '14px',
color: '#ff5722',
fontSize: '14px',
marginTop: '5px',
};

Expand All @@ -53,12 +53,14 @@ const { API_URL } = process.env;
function Home() {
const { data, loading } = useData(`${API_URL}/products`, {}, { method: 'GET' }, { ssr: true });

const getResizedImage = (imageUrl) => {
if (imageUrl) {
return `https://res.cloudinary.com/irfan-maulana-tkpd/image/fetch/c_fill,g_auto:face,h_200,fl_force_strip.progressive/f_webp/${encodeURIComponent(imageUrl)}`;
}
return '';
};
const getResizedImage = imageUrl => {
if (imageUrl) {
return `https://res.cloudinary.com/irfan-maulana-tkpd/image/fetch/c_fill,g_auto:face,h_130,fl_force_strip.progressive/f_webp/${encodeURIComponent(
imageUrl,
)}`;
}
return '';
};

return (
<div className="App" data-testid="home-container">
Expand All @@ -68,7 +70,8 @@ function Home() {
<div className="products" style={productWrapper}>
{data.data.map(item => (
<Link className="product" style={productCard} key={item.id} to={`/${item.id}`}>
<img className="product__img" style={productImg} src={getResizedImage(item.image)} alt={item.name}></img>
<LazyImage style={productImg} height="130px" src={getResizedImage(item.image)} alt={item.name} />

<div style={productInfo}>
<div style={productName}>{item.name}</div>
<div style={productPrice}>{item.price}</div>
Expand Down
10 changes: 10 additions & 0 deletions client/styles/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,13 @@ code {
border-left: 1px solid #fff;
border-right: 1px solid #fff;
}

.img {
transition: filter .5s linear;
}
.img.img--loading {
filter: blur(1px);
}
.img.img--loaded {
filter: blur(0);
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
},
"dependencies": {
"@babel/polyfill": "^7.10.4",
"@jackyef/use-intersect": "^0.0.6",
"@loadable/babel-plugin": "5.12.0",
"@loadable/component": "5.12.0",
"@loadable/server": "5.12.0",
Expand Down
3 changes: 2 additions & 1 deletion public/index.client.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="My App" />
<meta name="keywords" content="My App" />
<meta name="keywords" content="My App" />
<meta name="theme-color" content="#000000" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="mobile-web-app-capable" content="yes" />
Expand All @@ -19,6 +19,7 @@
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!-- Hotjar Tracking Code for https://tkpd-ta-web-vitals.glitch.me/ -->

<script>
(function(h,o,t,j,a,r){
h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1096,6 +1096,11 @@
dependencies:
"@hapi/hoek" "6.x.x"

"@jackyef/use-intersect@^0.0.6":
version "0.0.6"
resolved "https://registry.yarnpkg.com/@jackyef/use-intersect/-/use-intersect-0.0.6.tgz#423b1203ad82a1973be5a68492a9851551ea2846"
integrity sha512-rApoeUuQVYiQeZMkbboyJgn5fnvvEl6+ZOAINGR+acHhVBG0kxGGxA6JyeBTEbcyjBaT3eXVjdxy/zxBxzqj3A==

"@jest/console@^24.7.1":
version "24.7.1"
resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.7.1.tgz#32a9e42535a97aedfe037e725bd67e954b459545"
Expand Down

0 comments on commit ffff81b

Please sign in to comment.