목표
webpack 5 사용
stream을 이용해서 ssr 제공
react-router 적용하기
react-query로 api pretech 하기
local 환경에서 hmr 적용하기
js로 결과물을 ts로 변경하기
production과 local & dev 빌드 결과물 다르게 설정
번들링 분석 플러그인 설치
코드는 여기에서 확인
https://github.com/insidedw/react-webpack5-ssr/commit/b1f1132a20fbbbcb6d6e67861be91e7d9305ef74
print hello world · insidedw/react-webpack5-ssr@b1f1132
insidedw committed Jul 7, 2024
github.com
시작 전
linting 관련된 세팅은 생략
프로젝트 세팅
mkdir my-ssr-app
cd my-ssr-app
npm init -y
npm install react react-dom express
npm install -D webpack webpack-cli webpack-node-externals @babel/core @babel/preset-env @babel/preset-react babel-loader
프로젝트 구조
my-ssr-app/
├── public/
│ └── index.html
├── src/
│ ├── components/
│ │ └── App.js
│ ├── client.js
│ └── server.js
├── webpack/
│ ├── webpack.client.js
│ └── webpack.server.js
├── package.json
└── babel.config.js
바벨 설정
react 코드를 브라우저에서 읽어야 하니까
module.exports = {
presets: ['@babel/preset-env', '@babel/preset-react'],
};
서버 webpack 설정
webpack/webpack.server.js 파일을 생성하고 다음 내용을 추가
nodeExternals() 를 추가한 이유는 빌드에 node기본 라이브러리를 추가하지 말라고. 서버에는 이미 node가 설치되어 있으니까 그거 쓰면 된다.
서버 번들 파일 이름은 고정해도 된다. 배포 시 덮어씌우거나 지우고 새로운 파일을 생성 됨
const path = require('path');
const nodeExternals = require('webpack-node-externals');
module.exports = {
mode: 'development',
entry: './src/server.js',
target: 'node',
externals: [nodeExternals()],
output: {
path: path.resolve(__dirname, '../dist'),
filename: 'server.bundle.js',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
}
],
},
};
클라이언트 Webpack 설정
webpack/webpack.client.js 파일을 생성하고 다음 내용을 추가
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/client.js',
output: {
path: path.resolve(__dirname, '../dist'),
filename: 'client.bundle.js',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
}
],
},
};
React 컴포넌트 작성
src/components/App.js 파일을 생성하고 간단한 React 컴포넌트를 작성
import React from 'react';
const App = () => {
return (
<div>
<h1>Hello, SSR!</h1>
</div>
);
};
export default App;
클라이언트 엔트리
src/client.js 파일을 생성하고 다음 코드를 추가
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
ReactDOM.hydrate(<App />, document.getElementById('root'));
서버 엔트리
src/server.js 파일을 생성하고 다음 코드를 추가
import path from 'path';
import fs from 'fs';
import React from 'react';
import express from 'express';
import { renderToString } from 'react-dom/server';
import App from './components/App';
const app = express();
app.use(express.static('dist'));
app.get('*', (req, res) => {
const appString = renderToString(<App />);
const indexFile = path.resolve('./public/index.html');
fs.readFile(indexFile, 'utf8', (err, data) => {
if (err) {
console.error('Something went wrong:', err);
return res.status(500).send('Oops, better luck next time!');
}
return res.send(
data.replace('<div id="root"></div>', `<div id="root">${appString}</div>`)
);
});
});
app.listen(3000, () => {
console.log('Server is listening on port 3000');
});
HTML 파일 작성
public/index.html 파일을 생성하고 다음 내용을 추가합니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React SSR</title>
</head>
<body>
<div id="root"></div>
<script src="/client.bundle.js"></script>
</body>
</html>
NPM 스크립트 추가
package.json 파일의 scripts 섹션을 수정하여 빌드 및 서버 실행 스크립트를 추가합니다.
"scripts": {
"build": "webpack --config webpack/webpack.client.js && webpack --config webpack/webpack.server.js",
"start": "node dist/server.bundle.js"
}
프로젝트 빌드 및 실행
이제 프로젝트를 빌드하고 실행할 준비가 되었습니다.
npm run build
npm start
'IT > react' 카테고리의 다른 글
[react] ssr 프로젝트 만들기 (3) - css, js 번들에 hash 추가 (0) | 2024.07.02 |
---|---|
[react] ssr 프로젝트 만들기 (2) - css, 번들에 추가하기 (0) | 2024.07.02 |
[react] CRA 대신 webpack으로 react 프로젝트 구성하기 (0) | 2024.04.03 |
[react] Suspense (0) | 2024.03.26 |
[React] 컴포넌트 추상화 (0) | 2024.03.04 |