끄적
Hoc를 사용하여 코드 스플리팅
코드 스플리틍: 컴포넌트편
1. state에 기본값
2. 클릭했을때 호출: setState
3. 컴포넌트가 존재하면 보이기
1. state에 null 기본값
2. 클릭했을때 state에 set
3. 컴포넌트가 존재하면 보여주기: SpliteMe && <SpliteMe/>
매번 state에 담기가 귀찮으니까
Hoc을 사용 훅훅훅훅
Higher order component
주로 with~~~ 라고 지음
withRequest
기본원리
1. 파라미터로 컴포넌트를 받아오고
2. 함수 내부에서 새로운 컴포넌트를 만든 다음
3. 해당 컴포넌트 안에서 파라미터로 받아온 컴포넌트를 랜더링하는 것
코드스플리팅 함수 사용
해당 컴포넌트를 가지고 온다.
state 기본값 null 작성
가지고 온 컴포넌트가 있으면 setState
있으면 최종 랜더
라우팅
링크를 누르는 것과
해당 페이지를 불러오는 것은 별개이다.
reactDom Server. renderToString
- 동기적으로 작동
- 개인화 된 데이터는 서버 사이드 랜더링을 피한다.
prerender
- 검색엔진 최적화: 크롤러 일 경우에만 대신 랜더링해줘서 반환
koa 사용
정적 파일 제공
statc
- ja , css 파일을 서버에서 제공
koa-static 불러오고 -> 미들웨어
app.use(serve(path.resolve(__dirname, '../build/')));
app.use(ctx => {
ctx.body = 'Hello World';
});
클라이언트에서는 빌드를 해놓은 상태임
서비스 워커 때문에
서버에서 없어도 캐시 영향으로 페이지가 나옴
index.html
서버 측에서 준비되지 않은 요청이 들어왔을시
리액트 어플리케이션이 띄어져 있는 index.htm의 내용을 보여주어야 함
캐시를 비워도 사용 가능하게끔
노드는 jsx를 불러올수 없음
그래서 babel를 사용해야함
웹팩을 이용하여 리액트 관련 코드만 미리 빌드해서 사용하기
index.js에서
id가 root인 DOM을 찾아서 랜더링
서버를 위한 엔트리 파일
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import { StaticRouter } from 'react-router';
import App from 'shared/App';
const render = (location) => ReactDOMServer.renderToString(
<StaticRouter location={location}>
<App/>
</StaticRouter>
);
export default render;
이것을 웹팩으로 번들링 해주면 된다.
config 파일
===================================================================
use strict';
const path = require('path');
const webpack = require('webpack');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const getClientEnvironment = require('./env');
const paths = require('./paths');
const publicUrl = '';
const env = getClientEnvironment(publicUrl);
module.exports = {
entry: paths.serverRenderJs,
// Node.js 내장 모듈과 충돌이 일어나지 않으며 require 로 불러올 수 있는 형태로 번들링합니다
target: 'node',
output: {
// 정해준 서버 경로에 render.js 라는 파일명으로 저장합니다
path: paths.server,
filename: 'render.js',
libraryTarget: 'commonjs2' // node 에서 불러올 수 있도록, commonjs2 스타일로 번들링 합니다
},
resolve: {
modules: ['node_modules', paths.appNodeModules].concat(
process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
),
extensions: ['.js', '.json', '.jsx'],
},
module: {
strictExportPresence: true,
rules: [
// 자바스크립트 이외의 파일들을 무시합니다.
{
exclude: [
/\.(js|jsx)$/,
/\.json$/
],
loader: 'ignore',
},
// 자바스크립트는 Babel 을 통하여 트랜스파일링합니다
{
test: /\.(js|jsx)$/,
include: paths.appSrc,
loader: require.resolve('babel-loader'),
options: {
cacheDirectory: true,
},
}
],
},
plugins: [
// 필수 플러그인만 넣어줍니다
new webpack.DefinePlugin(env.stringified),
new CaseSensitivePathsPlugin(),
new WatchMissingNodeModulesPlugin(paths.appNodeModules),
]
};
-------------------------------------------------------------------------------
'use strict';
process.env.BABEL_ENV = 'production';
process.env.NODE_ENV = 'production';
/* 나중에 클라이언트쪽 코드에서 process.env.APP_ENV 값을 통하여
서버일때만, 혹은 브라우저일때만 특정한 작업을 하도록 설정 할 수 있습니다. */
process.env.APP_ENV = 'server';
process.on('unhandledRejection', err => {
throw err;
});
require('../config/env');
const webpack = require('webpack');
const config = require('../config/webpack.config.server'); // 서버용 환경설정을 지정
const paths = require('../config/paths');
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
if (!checkRequiredFiles([paths.serverRenderJs])) {
process.exit(1);
}
function build() {
console.log('Creating an server production build...');
let compiler = webpack(config);
return new Promise((resolve, reject) => {
compiler.run((err, stats) => {
if (err) {
return reject(err);
}
const messages = formatWebpackMessages(stats.toJson({}, true));
if (messages.errors.length) {
return reject(new Error(messages.errors.join('\n\n')));
}
return resolve({
stats,
warnings: messages.warnings,
});
});
});
}
build();
const fs = require('fs');
const path = require('path');
const render = require('./render').default; // ES6 형식으로 만들어진 모듈이므로, 뒤에 .default 를 붙여주어야합니다.
// html 내용을 해당 상수에 저장합니다
const template = fs.readFileSync(path.join(__dirname, '../../build/index.html'), { encoding: 'utf8'});
module.exports = (ctx) => {
// 요청이 들어올 때 현재 경로를 render 함수에 전달시켜서 문자열을 생성합니다
const location = ctx.path;
const rendered = render(location);
// 해당 문자열을, 템플릿에 있는 '<div id="root"></div> 사이에 넣어줍니다.
const page = template.replace('<div id="root"></div>', `<div id="root">${rendered}</div>`);
// 렌더링된 페이지를 반환합니다.
ctx.body = page;
}

"파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음"