From 9c0ed20a9db4d18b18d5224af047a4426acdb373 Mon Sep 17 00:00:00 2001 From: homuch Date: Fri, 5 Apr 2024 05:19:27 +0800 Subject: [PATCH] use webp as default; add responsive image --- client/package.json | 6 ++ client/src/components/ResImage.js | 62 +++++++++++++++++++ client/src/components/index.js | 3 +- .../src/views/out/home/services/Services.js | 40 +++++++++--- client/webpack.config.js | 17 +++++ 5 files changed, 117 insertions(+), 11 deletions(-) create mode 100644 client/src/components/ResImage.js diff --git a/client/package.json b/client/package.json index 121f0b64c..0301f3260 100644 --- a/client/package.json +++ b/client/package.json @@ -47,6 +47,7 @@ "html-react-parser": "^1.2.8", "html-webpack-plugin": "^5.3.2", "jodit-react": "^1.1.1", + "lazysizes": "^5.3.2", "path": "^0.12.7", "prop-types": "^15.7.2", "react": "^17.0.2", @@ -78,7 +79,9 @@ "eslint-plugin-prettier": "^3.4.0", "prettier": "2.3.2", "react-scripts": "^4.0.3", + "responsive-loader": "3.1.2", "sass": "^1.35.1", + "sharp": "0.32.6", "tsparticles": "^2.0.6" }, "scripts": { @@ -99,5 +102,8 @@ "engines": { "node": ">=10", "npm": ">=6" + }, + "imports": { + "#assets/*": "./src/assets/*" } } diff --git a/client/src/components/ResImage.js b/client/src/components/ResImage.js new file mode 100644 index 000000000..4464d62e6 --- /dev/null +++ b/client/src/components/ResImage.js @@ -0,0 +1,62 @@ +import React from 'react' +import propType from 'prop-types' +import { CImage } from '@coreui/react' + +import 'lazysizes' +import 'lazysizes/plugins/attrchange/ls.attrchange' +import 'lazysizes/plugins/respimg/ls.respimg.js' + +/** + * ResImage component displays an image with lazy loading support and multiple image sources. + * + * @component + * @param {Object} props - The component props. + * @param {Object} props.avifSrc - The AVIF image source object. + * @param {Object} props.jpgSrc - The JPG image source object. + * @param {Object} props.webpSrc - The WebP image source object. + * @param {string} props.alt - The alternative text for the image. + * @param {boolean} props.lazySize - Enable this help provide an actual size automatically to load proper size size, but since it will deffer the image load, **don't use it for images that user can see at the first glance.** + * @param {string} props.sizes - The sizes attribute for the image. For images near to top, please use it instead of lazySize. + * @param {string} props.className - The CSS class name for the image. + * @returns {JSX.Element} The rendered ResImage component. + */ +const ResImage = ({ avifSrc, jpgSrc, webpSrc, alt, lazySize, sizes, ...props }) => { + return lazySize ? ( + + {avifSrc && } + {webpSrc && } + + + ) : ( + + {avifSrc && } + {webpSrc && } + + + ) +} + +ResImage.propTypes = { + avifSrc: propType.any, + jpgSrc: propType.any, + webpSrc: propType.any, + alt: propType.string, + className: propType.string, + lazySize: propType.bool, + sizes: propType.string, +} + +export default ResImage diff --git a/client/src/components/index.js b/client/src/components/index.js index a93268e01..678d132dd 100644 --- a/client/src/components/index.js +++ b/client/src/components/index.js @@ -5,7 +5,7 @@ import AppHeaderDropdown from './header/AppHeaderDropdown' import AppSidebar from './AppSidebar' import AppBackground from './AppBackground' import { AppFallbackRender } from './AppFallbackRender' - +import ResImage from './ResImage' export { AppContent, AppFooter, @@ -14,4 +14,5 @@ export { AppSidebar, AppBackground, AppFallbackRender, + ResImage, } diff --git a/client/src/views/out/home/services/Services.js b/client/src/views/out/home/services/Services.js index 5a66290c9..388e7e1c6 100644 --- a/client/src/views/out/home/services/Services.js +++ b/client/src/views/out/home/services/Services.js @@ -1,11 +1,7 @@ /* eslint-disable prettier/prettier */ +import { CContainer, CRow } from '@coreui/react' import React from 'react' -import { CContainer, CRow, CImage } from '@coreui/react' -import studyabroad from '../../../../assets/images/studyabroad.png' -import column from '../../../../assets/images/column.png' -import communicate from '../../../../assets/images/communicate.png' -import career from '../../../../assets/images/career.png' - +import { ResImage } from '../../../../components' const Services = () => { return (
@@ -21,7 +17,13 @@ const Services = () => {
{' '}
- +

通訊錄

@@ -33,7 +35,13 @@ const Services = () => {

{' '}
- +

徵才求職

@@ -45,7 +53,13 @@ const Services = () => {

{' '}
- +

留學資訊

@@ -57,7 +71,13 @@ const Services = () => {

{' '}
- +

採訪文章

diff --git a/client/webpack.config.js b/client/webpack.config.js index cd749cbda..6c70df127 100644 --- a/client/webpack.config.js +++ b/client/webpack.config.js @@ -69,6 +69,23 @@ module.exports = { test: /\.(scss)$/, use: ['style-loader', 'css-loader', 'sass-loader'], }, + { + test: /\.(png|jpe?g|gif|webp|avif)$/i, + use: [ + { + loader: 'responsive-loader', + options: { + adapter: require('responsive-loader/sharp'), + sizes: [480, 960, 1500], + placeholder: true, + placeholderSize: 40, + pregressive: true, + format: 'webp', // ? or 'avif' in the future + }, + }, + ], + type: 'javascript/auto', + }, { test: /\.(png|svg|jpg|gif)$/, use: {