Skip to content

Commit e22b9f0

Browse files
authored
Perf/#368-S : SEO 를 위한 meta 태그 추가 (#374)
* setting : seo를 위한 react-helmet-async 설치 * chore : splitVendorChunkPlugin 설정 제거 * feat : SEO를 위한 MetaHelmet 컴포넌트 구현
1 parent a642dc0 commit e22b9f0

File tree

8 files changed

+213
-161
lines changed

8 files changed

+213
-161
lines changed

client/index.html

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8" />
5-
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
6-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7-
<title>Wabinar</title>
85
</head>
96
<body>
107
<div id="root"></div>

client/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@
1010
},
1111
"dependencies": {
1212
"@react-icons/all-files": "^4.1.0",
13+
"@types/react-helmet": "^6.1.6",
1314
"axios": "^1.1.3",
1415
"classnames": "^2.3.2",
1516
"eventemitter3": "^5.0.0",
1617
"react": "^18.2.0",
1718
"react-dom": "^18.2.0",
19+
"react-helmet-async": "^1.3.0",
1820
"react-loader-spinner": "^5.3.4",
1921
"react-router-dom": "^6.4.3",
2022
"react-toastify": "^9.1.1",

client/src/App.tsx

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState, useEffect } from 'react';
1+
import { useEffect, useState } from 'react';
22
import { Route, Routes, useLocation, useNavigate } from 'react-router-dom';
33
import { getAuth } from 'src/apis/auth';
44
import UserContext from 'src/contexts/user';
@@ -12,6 +12,7 @@ import {
1212
import { User } from 'src/types/user';
1313

1414
import 'styles/reset.scss';
15+
import MetaHelmet from './components/MetaHelmet';
1516

1617
function App() {
1718
const [user, setUser] = useState<User | null>(null);
@@ -36,17 +37,22 @@ function App() {
3637
autoLogin();
3738
}, []);
3839

39-
return isLoaded ? (
40-
<UserContext.Provider value={{ user, setUser }}>
41-
<Routes>
42-
<Route path="/" element={<LoginPage />} />
43-
<Route path="/oauth" element={<OAuthPage />} />
44-
<Route path="/workspace/*" element={<WorkspacePage />} />
45-
<Route path="/404" element={<NotFoundPage />} />
46-
</Routes>
47-
</UserContext.Provider>
48-
) : (
49-
<LoadingPage />
40+
return (
41+
<>
42+
<MetaHelmet title="화상회의와 회의록 작성을 한번에, Wabinar" />
43+
{isLoaded ? (
44+
<UserContext.Provider value={{ user, setUser }}>
45+
<Routes>
46+
<Route path="/" element={<LoginPage />} />
47+
<Route path="/oauth" element={<OAuthPage />} />
48+
<Route path="/workspace/*" element={<WorkspacePage />} />
49+
<Route path="/404" element={<NotFoundPage />} />
50+
</Routes>
51+
</UserContext.Provider>
52+
) : (
53+
<LoadingPage />
54+
)}
55+
</>
5056
);
5157
}
5258

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { Helmet } from 'react-helmet-async';
2+
import { META_INFO } from 'src/constants/meta';
3+
4+
interface MetaHelmetProps {
5+
title: string;
6+
}
7+
8+
// TODO: 페이지별 다른 title 적용하도록 할 것
9+
function MetaHelmet({ title }: MetaHelmetProps) {
10+
return (
11+
<Helmet>
12+
<title>{title}</title>
13+
14+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
15+
<meta name="description" content={META_INFO.description} />
16+
<meta name="keywords" content={META_INFO.keywords} />
17+
18+
<meta property="og:type" content="website" />
19+
<meta property="og:title" content={META_INFO.title} />
20+
<meta property="og:site_name" content={META_INFO.title} />
21+
<meta property="og:type" content={META_INFO.type} />
22+
<meta property="og:description" content={META_INFO.description} />
23+
<meta property="og:image" content={META_INFO.image} />
24+
<meta property="og:url" content={META_INFO.url} />
25+
26+
<meta name="twitter:title" content={META_INFO.title} />
27+
<meta name="twitter:description" content={META_INFO.description} />
28+
<meta name="twitter:image" content={META_INFO.image} />
29+
30+
<link rel="canonical" href={META_INFO.url} />
31+
</Helmet>
32+
);
33+
}
34+
export default MetaHelmet;

client/src/constants/meta.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export const META_INFO = {
2+
title: '화상회의와 회의록 작성을 한번에, Wabinar',
3+
description: '회의와 기록을 한번에',
4+
keywords: '회의툴, 공유 회의록, 화상회의, 실시간 공동 편집',
5+
url: 'https://www.wabinar.live',
6+
href: '/favicon.svg',
7+
type: 'website',
8+
image: '/favicon.svg',
9+
};

client/src/main.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import ReactDOM from 'react-dom/client';
2+
import { HelmetProvider } from 'react-helmet-async';
23
import { BrowserRouter } from 'react-router-dom';
34

45
import 'react-toastify/dist/ReactToastify.css';
@@ -7,7 +8,9 @@ import Toaster from './components/common/Toaster';
78

89
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
910
<BrowserRouter>
10-
<App />
11-
<Toaster />
11+
<HelmetProvider>
12+
<App />
13+
<Toaster />
14+
</HelmetProvider>
1215
</BrowserRouter>,
1316
);

client/vite.config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { resolve } from 'path';
22

33
import react from '@vitejs/plugin-react';
4-
import { defineConfig, splitVendorChunkPlugin } from 'vite';
4+
import { defineConfig } from 'vite';
55

66
// https://vitejs.dev/config/
77
export default defineConfig({
8-
plugins: [react(), splitVendorChunkPlugin()],
8+
plugins: [react()],
99
resolve: {
1010
alias: [
1111
{ find: 'src', replacement: resolve(__dirname, './src') },

0 commit comments

Comments
 (0)