feat(v2): optimize image processing with sharp & lqip (#1663)
* feat(v2): optimize image processing * cleanup
|
@ -49,8 +49,10 @@
|
|||
"fs-extra": "^7.0.0",
|
||||
"globby": "^9.2.0",
|
||||
"html-webpack-plugin": "^4.0.0-beta.5",
|
||||
"image-webpack-loader": "^5.0.0",
|
||||
"import-fresh": "^3.0.0",
|
||||
"lodash": "^4.17.14",
|
||||
"lqip-loader": "^2.2.0",
|
||||
"mini-css-extract-plugin": "^0.7.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"null-loader": "^3.0.0",
|
||||
|
@ -58,12 +60,16 @@
|
|||
"portfinder": "^1.0.20",
|
||||
"react-dev-utils": "^9.0.1",
|
||||
"react-helmet": "^6.0.0-beta",
|
||||
"react-ideal-image": "^0.0.5",
|
||||
"react-loadable": "^5.5.0",
|
||||
"react-loadable-ssr-addon": "^0.1.8",
|
||||
"react-router": "^5.0.1",
|
||||
"react-router-config": "^5.0.1",
|
||||
"react-router-dom": "^5.0.1",
|
||||
"react-waypoint": "8.0.3",
|
||||
"responsive-loader": "^1.2.0",
|
||||
"semver": "^6.1.1",
|
||||
"sharp": "^0.22.1",
|
||||
"shelljs": "^0.8.3",
|
||||
"static-site-generator-webpack-plugin": "^3.4.2",
|
||||
"std-env": "^2.2.1",
|
||||
|
|
29
packages/docusaurus/src/client/exports/Image.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* Copyright (c) 2017-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
import React from 'react';
|
||||
import IdealImage from 'react-ideal-image';
|
||||
|
||||
function Image(props) {
|
||||
const {alt, className, img} = props;
|
||||
return (
|
||||
<IdealImage
|
||||
{...props}
|
||||
alt={alt}
|
||||
className={className}
|
||||
height={img.src.height}
|
||||
placeholder={{lqip: img.preSrc}}
|
||||
src={img.src.src}
|
||||
srcSet={img.src.images.map(image => ({
|
||||
...image,
|
||||
src: image.path,
|
||||
}))}
|
||||
width={img.src.width}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default Image;
|
|
@ -156,6 +156,20 @@ export function createBaseConfig(
|
|||
exportOnlyLocals: isServer,
|
||||
}),
|
||||
},
|
||||
{
|
||||
test: /\.(gif|png|jpe?g)$/i,
|
||||
use: [
|
||||
'lqip-loader',
|
||||
{
|
||||
loader: 'responsive-loader',
|
||||
options: {
|
||||
adapter: require('responsive-loader/sharp'),
|
||||
sizes: [300, 600, 900, 1200],
|
||||
},
|
||||
},
|
||||
'image-webpack-loader',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
|
|
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 155 KiB |
Before Width: | Height: | Size: 223 KiB After Width: | Height: | Size: 223 KiB |
Before Width: | Height: | Size: 200 KiB After Width: | Height: | Size: 200 KiB |
Before Width: | Height: | Size: 197 KiB After Width: | Height: | Size: 197 KiB |
Before Width: | Height: | Size: 188 KiB After Width: | Height: | Size: 188 KiB |
|
@ -10,7 +10,7 @@ const users = [
|
|||
{
|
||||
title: 'Channel.js',
|
||||
description: 'The missing constructor for creating safe async iterators',
|
||||
preview: '/img/showcase/channeljs.png',
|
||||
preview: require('./showcase/channeljs.png'),
|
||||
website: 'https://channel.js.org',
|
||||
source: 'https://github.com/channeljs/channel',
|
||||
fbOpenSource: false,
|
||||
|
@ -19,7 +19,7 @@ const users = [
|
|||
{
|
||||
title: 'Component Kit',
|
||||
description: 'A declarative UI framework for iOS',
|
||||
preview: '/img/showcase/componentkit.png',
|
||||
preview: require('./showcase/componentkit.png'),
|
||||
website: 'https://componentkit.org',
|
||||
source: 'https://github.com/facebook/componentkit',
|
||||
fbOpenSource: true,
|
||||
|
@ -28,7 +28,7 @@ const users = [
|
|||
{
|
||||
title: 'Flux',
|
||||
description: 'Application architecture for building user interfaces',
|
||||
preview: '/img/showcase/flux.png',
|
||||
preview: require('./showcase/flux.png'),
|
||||
website: 'https://facebook.github.io/flux/',
|
||||
source: 'https://github.com/facebook/flux',
|
||||
fbOpenSource: true,
|
||||
|
@ -37,7 +37,7 @@ const users = [
|
|||
{
|
||||
title: 'Hermes',
|
||||
description: 'JavaScript engine optimized for React Native',
|
||||
preview: '/img/showcase/hermes.png',
|
||||
preview: require('./showcase/hermes.png'),
|
||||
website: 'https://hermesengine.dev',
|
||||
source: 'https://github.com/facebook/hermes',
|
||||
fbOpenSource: true,
|
||||
|
@ -46,7 +46,7 @@ const users = [
|
|||
{
|
||||
title: 'uniforms',
|
||||
description: 'A set of React libraries for building forms',
|
||||
preview: '/img/showcase/uniforms.png',
|
||||
preview: require('./showcase/uniforms.png'),
|
||||
website: 'https://uniforms.tools/',
|
||||
source: 'https://github.com/vazco/uniforms',
|
||||
fbOpenSource: false,
|
||||
|
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 86 KiB |
|
@ -9,6 +9,7 @@ import React from 'react';
|
|||
import Link from '@docusaurus/Link';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import withBaseUrl from '@docusaurus/withBaseUrl';
|
||||
import Image from '@docusaurus/Image';
|
||||
|
||||
import Layout from '@theme/Layout';
|
||||
|
||||
|
@ -18,7 +19,7 @@ import styles from './styles.module.css';
|
|||
|
||||
const QUOTES = [
|
||||
{
|
||||
thumbnail: 'img/christopher-chedeau.jpg',
|
||||
thumbnail: require('./christopher-chedeau.jpg'),
|
||||
name: 'Christopher "vjeux" Chedeau',
|
||||
title: 'Lead Prettier Developer',
|
||||
text: (
|
||||
|
@ -34,7 +35,7 @@ const QUOTES = [
|
|||
),
|
||||
},
|
||||
{
|
||||
thumbnail: 'img/hector-ramos.png',
|
||||
thumbnail: require('./hector-ramos.png'),
|
||||
name: 'Hector Ramos',
|
||||
title: 'Lead React Native Advocate',
|
||||
text: (
|
||||
|
@ -47,7 +48,7 @@ const QUOTES = [
|
|||
),
|
||||
},
|
||||
{
|
||||
thumbnail: 'img/ricky-vetter.jpg',
|
||||
thumbnail: require('./ricky-vetter.jpg'),
|
||||
name: 'Ricky Vetter',
|
||||
title: 'ReasonReact Developer',
|
||||
text: (
|
||||
|
@ -197,10 +198,10 @@ function Home() {
|
|||
{QUOTES.map(quote => (
|
||||
<div className="col" key={quote.name}>
|
||||
<div className="avatar avatar--vertical margin-bottom--sm">
|
||||
<img
|
||||
<Image
|
||||
alt={quote.name}
|
||||
className="avatar__photo avatar__photo--xl"
|
||||
src={withBaseUrl(quote.thumbnail)}
|
||||
img={quote.thumbnail}
|
||||
/>
|
||||
<div className="avatar__intro">
|
||||
<h4 className="avatar__name">{quote.name}</h4>
|
||||
|
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
import React, {useEffect} from 'react';
|
||||
import Image from '@docusaurus/Image';
|
||||
import Layout from '@theme/Layout';
|
||||
|
||||
import classnames from 'classnames';
|
||||
|
@ -42,7 +43,7 @@ function Showcase() {
|
|||
<div className="col col--4">
|
||||
<div className={classnames('card', styles.showcaseUser)}>
|
||||
<div className="card__image">
|
||||
<img src={user.preview} alt={user.title} />
|
||||
<Image img={user.preview} alt={user.title} />
|
||||
</div>
|
||||
<div className="card__body">
|
||||
<div class="avatar">
|
||||
|
|