Skip to content

Commit

Permalink
[개인 미션 - 성능 오답노트] 도담(김민재) 미션 제출합니다. (#99)
Browse files Browse the repository at this point in the history
* chore: 홈페이지 url 설정 및 필요 패키지 추가

* refactor: css 관련 minimize 작업 및 코드 스플리팅

* refactor: react lazy 추가 및 suspense 적용

* refactor: 내장 미디어 파일 최적화 작업

* refactor: 최적화한 asset 파일의 확장자에 맞추어 태그 변경 및 최적화 코드 추가

* refactor: layout shift 최소화를 위한 reflow 작업 제거

* refactor: 검색 초기 페이지 데이터 캐싱

* refactor: 폰트 최적화

* refactor: 이미지 최적화

* refactor: webpackChunkName 지정

* refactor: 불필요한 태그 삭제

* refactor: 주석 삭제
  • Loading branch information
D0Dam committed Sep 11, 2023
1 parent cf16a0c commit 7fe7105
Show file tree
Hide file tree
Showing 22 changed files with 75 additions and 36 deletions.
5 changes: 4 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
rel="preload"
as="style"
href="https://fonts.googleapis.com/css2?family=Josefin+Sans:ital,wght@0,400;0,700;1,400;1,700&display=swap"
rel="stylesheet"
onload="this.onload=null; this.rel='stylesheet'"
crossorigin
/>
<title>memegle - gif search engine for you</title>
</head>
Expand Down
23 changes: 16 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
"build:prod": "webpack --mode=production --node-env=production",
"watch": "webpack --watch",
"serve": "webpack serve --mode=development",
"serve:prod": "webpack serve --mode=production --node-env=production",
"prettier": "prettier --write .",
"deploy": "npm run build:prod && npx gh-pages -d dist"
},
"keywords": [],
"author": "woowacourse",
"homepage": "https://{username}.github.io/perf-basecamp",
"homepage": "https://d0dam.github.io/perf-basecamp",
"license": "MIT",
"dependencies": {
"@giphy/js-fetch-api": "^4.1.1",
Expand All @@ -33,13 +34,14 @@
"@types/react": "^18.0.17",
"@types/react-dom": "^18.0.6",
"@types/react-router-dom": "^5.3.3",
"@typescript-eslint/eslint-plugin": "^5.35.1",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@webpack-cli/generators": "^2.2.0",
"babel-loader": "^8.2.2",
"copy-webpack-plugin": "^9.0.1",
"css-loader": "^6.2.0",
"css-minimizer-webpack-plugin": "^5.0.1",
"dotenv-webpack": "^7.0.3",
"eslint": "^7.32.0",
"eslint": "^8.0.1",
"eslint-config-prettier": "^8.5.0",
"eslint-config-standard-with-typescript": "^22.0.0",
"eslint-plugin-hooks": "^0.4.3",
Expand All @@ -50,21 +52,28 @@
"file-loader": "^6.2.0",
"html-loader": "^2.1.2",
"html-webpack-plugin": "^5.3.2",
"mini-css-extract-plugin": "^2.7.6",
"prettier": "^2.3.2",
"style-loader": "^3.2.1",
"ts-loader": "^9.3.1",
"typescript": "^4.8.2",
"webpack": "^5.50.0",
"webpack": "^5.88.2",
"webpack-bundle-analyzer": "^4.9.1",
"webpack-cli": "^4.7.2",
"webpack-dev-server": "^3.11.2"
},
"babel": {
"presets": [
"@babel/preset-env",
"@babel/preset-react"
"@babel/preset-react",
{
"modules": false
}
],
"plugins": [
"@babel/plugin-transform-runtime"
]
}
},
"sideEffects": [
"*.css"
]
}
7 changes: 4 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { lazy } from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';

import Home from './pages/Home/Home';
import Search from './pages/Search/Search';
const Home = lazy(() => import(/* webpackChunkName: "home" */ './pages/Home/Home'));
const Search = lazy(() => import(/* webpackChunkName: "search" */ './pages/Search/Search'));

import NavBar from './components/NavBar/NavBar';
import Footer from './components/Footer/Footer';
Expand All @@ -10,7 +11,7 @@ import './App.css';

const App = () => {
return (
<Router basename={'/perf-basecamp'}>
<Router>
<NavBar />
<Routes>
<Route path="/" element={<Home />} />
Expand Down
Binary file removed src/assets/images/find.gif
Binary file not shown.
Binary file added src/assets/images/find.mp4
Binary file not shown.
Binary file removed src/assets/images/free.gif
Binary file not shown.
Binary file added src/assets/images/free.mp4
Binary file not shown.
Binary file removed src/assets/images/hero.png
Binary file not shown.
Binary file added src/assets/images/hero.webp
Binary file not shown.
Binary file removed src/assets/images/trending.gif
Binary file not shown.
Binary file added src/assets/images/trending.mp4
Binary file not shown.
3 changes: 3 additions & 0 deletions src/data/gifCache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import type { GifImageModel } from '../models/image/gifImage';

export let gifCache: GifImageModel[] = [];
7 changes: 6 additions & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { createRoot } from 'react-dom/client';
import App from './App';
import { Suspense } from 'react';

const root = createRoot(document.getElementById('app')!);
root.render(<App />);
root.render(
<Suspense fallback={<div>로딩중입니다.</div>}>
<App />
</Suspense>
);
11 changes: 6 additions & 5 deletions src/pages/Home/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { useRef } from 'react';
import { Link } from 'react-router-dom';
import classNames from 'classnames/bind';

import heroImage from '../../assets/images/hero.png';
import trendingGif from '../../assets/images/trending.gif';
import findGif from '../../assets/images/find.gif';
import freeGif from '../../assets/images/free.gif';
import heroImage from '../../assets/images/hero.webp';
import trendingGif from '../../assets/images/trending.mp4';
import findGif from '../../assets/images/find.mp4';
import freeGif from '../../assets/images/free.mp4';

import FeatureItem from './components/FeatureItem/FeatureItem';
import CustomCursor from './components/CustomCursor/CustomCursor';
Expand All @@ -19,7 +19,8 @@ const Home = () => {
return (
<>
<section className={styles.heroSection}>
<img className={styles.heroImage} src={heroImage} alt="hero image" />
<img className={styles.heroImage} src={heroImage} alt="hero" />

<div className={styles.projectTitle}>
<h1 className={styles.title}>Memegle</h1>
<h3 className={styles.subtitle}>gif search engine for you</h3>
Expand Down
3 changes: 1 addition & 2 deletions src/pages/Home/components/CustomCursor/CustomCursor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ const CustomCursor = ({ text = '' }: CustomCursorProps) => {

useEffect(() => {
if (cursorRef.current) {
cursorRef.current.style.top = `${mousePosition.pageY}px`;
cursorRef.current.style.left = `${mousePosition.pageX}px`;
cursorRef.current.style.transform = `translate(${mousePosition.pageX}px, ${mousePosition.pageY}px)`;
}
}, [mousePosition]);

Expand Down
2 changes: 1 addition & 1 deletion src/pages/Home/components/FeatureItem/FeatureItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type FeatureItemProps = {
const FeatureItem = ({ title, imageSrc }: FeatureItemProps) => {
return (
<div className={styles.featureItem}>
<img className={styles.featureImage} src={imageSrc} />
<video src={imageSrc} className={styles.featureImage} autoPlay muted loop playsInline />
<div className={styles.featureTitleBg}></div>
<h4 className={styles.featureTitle}>{title}</h4>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/Search/components/GifItem/GifItem.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
}

.gifItem:hover {
top: -0.75rem;
transform: translateY(-0.75rem);
}

.gifImage {
Expand Down
4 changes: 2 additions & 2 deletions src/pages/Search/components/GifItem/GifItem.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { memo } from 'react';
import { GifImageModel } from '../../../../models/image/gifImage';

import styles from './GifItem.module.css';

type GifItemProps = Omit<GifImageModel, 'id'>;
Expand All @@ -16,4 +16,4 @@ const GifItem = ({ imageUrl = '', title = '' }: GifItemProps) => {
);
};

export default GifItem;
export default memo(GifItem);
2 changes: 1 addition & 1 deletion src/pages/Search/components/HelpPanel/HelpPanel.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
}

.selectedItemContainer.showSheet {
right: 0;
transform: translateX(-320px);
opacity: 1;
}

Expand Down
16 changes: 12 additions & 4 deletions src/pages/Search/hooks/useGifSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ChangeEvent, useEffect, useState } from 'react';

import { gifAPIService } from '../../../apis/gifAPIService';
import { GifImageModel } from '../../../models/image/gifImage';
import { gifCache } from '../../../data/gifCache';

const DEFAULT_PAGE_INDEX = 0;

Expand All @@ -12,7 +13,7 @@ export const SEARCH_STATUS = {
NO_RESULT: 'NO_RESULT'
} as const;

export type SearchStatus = typeof SEARCH_STATUS[keyof typeof SEARCH_STATUS];
export type SearchStatus = (typeof SEARCH_STATUS)[keyof typeof SEARCH_STATUS];

const useGifSearch = () => {
const [status, setStatus] = useState<SearchStatus>(SEARCH_STATUS.BEFORE_SEARCH);
Expand Down Expand Up @@ -57,11 +58,18 @@ const useGifSearch = () => {
useEffect(() => {
const fetch = async () => {
if (status === SEARCH_STATUS.BEFORE_SEARCH) {
const gifs: GifImageModel[] = await gifAPIService.getTrending();

setGifList(gifs);
if (gifCache.length === 0) {
const gifs: GifImageModel[] = await gifAPIService.getTrending();

gifCache.push(...gifs);
setGifList(gifs);
}
if (gifCache.length !== 0) {
setGifList(gifCache);
}
}
};

fetch();

return () => setStatus(SEARCH_STATUS.LOADING);
Expand Down
2 changes: 2 additions & 0 deletions src/types/images.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ declare module '*.png';
declare module '*.jpg';
declare module '*.gif';
declare module '*.svg';
declare module '*.webp';
declare module '*.mp4';
24 changes: 16 additions & 8 deletions webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const Dotenv = require('dotenv-webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
entry: './src/index.tsx',
resolve: { extensions: ['.ts', '.tsx', '.js', '.jsx'] },
output: {
filename: 'bundle.js',
filename: 'bundle.[chunkhash].js',
path: path.join(__dirname, '/dist'),
clean: true
},
Expand All @@ -18,16 +21,24 @@ module.exports = {
},
devtool: 'source-map',
plugins: [
new BundleAnalyzerPlugin(),
new HtmlWebpackPlugin({
template: './index.html'
}),
new CopyWebpackPlugin({
patterns: [{ from: './public', to: './public' }]
}),
new Dotenv()
new Dotenv(),
new MiniCssExtractPlugin({
filename: '[name].css'
})
],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader']
},
{
test: /\.(js|jsx|ts|tsx)$/i,
exclude: /node_modules/,
Expand All @@ -36,11 +47,7 @@ module.exports = {
}
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader']
},
{
test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i,
test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif|mp4|webm|webp)$/i,
loader: 'file-loader',
options: {
name: 'static/[name].[ext]'
Expand All @@ -49,6 +56,7 @@ module.exports = {
]
},
optimization: {
minimize: false
splitChunks: { chunks: 'all' },
minimizer: ['...', new CssMinimizerPlugin()]
}
};

0 comments on commit 7fe7105

Please sign in to comment.