Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
はじめてのSSR
Search
Taketoshi Aono(青野健利 a.k.a brn)
August 31, 2017
Programming
3
1.2k
はじめてのSSR
React + ReduxでSSR+Isomorphicなアプリケーションを作ったときにつまづいた点をまとめました。
Node学園27時限目
Taketoshi Aono(青野健利 a.k.a brn)
August 31, 2017
Tweet
Share
More Decks by Taketoshi Aono(青野健利 a.k.a brn)
See All by Taketoshi Aono(青野健利 a.k.a brn)
document.write再考
brn
6
3k
Parsing Javascript
brn
13
9.1k
JSON & Object Tips
brn
1
440
CA 1Day Youth Bootcamp for Frontend LT
brn
0
870
Modern TypeScript
brn
2
770
javascript - behind the scene
brn
3
710
tc39 proposals
brn
0
830
プロダクト開発とTypeScript
brn
8
2.9k
React-Springでリッチなアニメーション
brn
1
650
Other Decks in Programming
See All in Programming
お前もAI鬼にならないか?👹Bolt & Cursor & Supabase & Vercelで人間をやめるぞ、ジョジョー!👺
taishiyade
7
4.1k
昭和の職場からアジャイルの世界へ
kumagoro95
1
410
Boost Performance and Developer Productivity with Jakarta EE 11
ivargrimstad
0
620
Flutter × Firebase Genkit で加速する生成 AI アプリ開発
coborinai
0
170
CSS Linter による Baseline サポートの仕組み
ryo_manba
1
140
クリーンアーキテクチャから見る依存の向きの大切さ
shimabox
4
910
Djangoアプリケーション 運用のリアル 〜問題発生から可視化、最適化への道〜 #pyconshizu
kashewnuts
1
260
ファインディLT_ポケモン対戦の定量的分析
fufufukakaka
0
890
責務と認知負荷を整える! 抽象レベルを意識した関心の分離
yahiru
8
1.3k
第3回 Snowflake 中部ユーザ会- dbt × Snowflake ハンズオン
hoto17296
4
380
Visual StudioのGitHub Copilotでいろいろやってみる
tomokusaba
1
190
sappoRo.R #12 初心者セッション
kosugitti
0
270
Featured
See All Featured
Reflections from 52 weeks, 52 projects
jeffersonlam
348
20k
Speed Design
sergeychernyshev
27
800
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.1k
Building an army of robots
kneath
303
45k
Scaling GitHub
holman
459
140k
Typedesign – Prime Four
hannesfritz
40
2.5k
How to Think Like a Performance Engineer
csswizardry
22
1.4k
The World Runs on Bad Software
bkeepers
PRO
67
11k
Building Adaptive Systems
keathley
40
2.4k
The Language of Interfaces
destraynor
156
24k
Automating Front-end Workflow
addyosmani
1368
200k
StorybookのUI Testing Handbookを読んだ
zakiyama
28
5.5k
Transcript
ⴱ ג ך S S R
せ: @brn (ꫬꅿ⨳ⵃa.k.a ـٕ٦ظ) 耵噟: ؿٗٝزؒٝسؒٝآص،٥iOSؒٝآص، ⠓爡: Cyberagent ،سذؙأةآؔRightSegment٥AI Messenger
ـؚٗ: http://abcdef.gets.b6n.ch/ Twitter: https://twitter.com/brn227 GitHub: https://github.com/brn
⡦⠗ְִךַ ְׂSSR׃״ֲהׅהꬊ䌢ח넝䏝זֿה׃גְ鎸✲כ״ֻ 鋅ַֽךָծ ⴱ娄涸ז㉏겗ח瘶ִגְךָ㼰זְ״ֲח䙼ִկ זךדծSSR+Isomorphicז圓䧭ד،فٔ⡲♳ד䝢ֿהծ 㹋ꥷח鍑寸׃倯岀⚛ץגկ
Language ְא鸐typescript鼅䫛׃կ ֿ荈⡤כNodeJS⩎הـٓؐؠ⩎דٌرٕךinterface㹀纏ָ⢪ְת ׇגꬊ䌢ח葺ַկַזىأָ幾կ 暴חAPIךٖأهٝأךأؗ٦وⰟ鸐ךٌآُ٦ٕחInterfaceה ׃ג㹀纏ׅהծ 涸חAPIךؒٓ٦鋅אֽךד葺ְկ
Library/Framework ـٓؐؠ⩎כReact(v16.0β) + Redux + React-Router v4 ؟٦غ؟؎سכExpress + Sequelize
+ MySQL NodeJSך湊鋔כsupervisord
Structure ֿֿכꬊ䌢ח䝢կָծ 如ل٦آך״ֲז圓䧭ח׃կ
server NodeJSך؟٦غ٦㹋鄲 DB،ؙإأהַ client ـٓؐؠ⩎ך㹋鄲 React + Redux isomorphic NodeJSהـٓؐؠ⩎דⰟ鸐ׅ㘗㹀纏הַ
Root rendering SSR欽ך؟٦غ٦
HTML Rendering Reactך؝ٝه٦طٝزכ֮ךָծHTMLةؚろⰋ⡤ךٖ ٝتؚٔٝוֲַׅ䝢կ 穠㽷HTMLةؚװHeadةؚReactד㹋鄲׃גծ؟٦غ؟؎سדٖ ٝتؚׅٔٝة؎ىؚٝךծך؝ٝه٦طٝز⢪կ
data-reactid HTMLⰋ⡤Reactדٖٝتؚׅٔٝהـٓؐؠ⩎דmountׅה ֹחdata-reactidָ׆גWarningָדָծ React v16ַכdata-reactid涪遤׃זֻזךדWarningָ嶊 ִկ
Redux State of SSR SSRדⴱ劍朐䡾ٖٝتؚׅٔٝחծ 剑ⴱכ؟٦غ؟؎سדdbַ《䖤׃ؒٝذ؍ذ؍湫䱸床׃גְ կ ׃ַ׃ծֿהAPIؒٝسه؎ٝزך✳ꅾ盖椚ָ涪欰ׅկ
viewָ《䖤ׅر٦ةָ㢌הֹחծ ؟٦غ⩎ךؒٝذ؍ذ؍《䖤鿇ⴓ⥜姻ָ䗳銲ד✳ꅾ盖椚חזկ APIエンドポイント DB React ؒٝذ؍ذ؍湫䱸《䖤 Reactח床ׅ ブラウザ
Redux State of SSR DRYחװծ 㹋ꥷחredux-saga⹛⡲ׇׁג؟٦غ٦ⰻדlocalhostד荈魦ךؒٝ سه؎ٝز〨ְկ fetch⢪גְךדծisomorphic-fetchػح؛٦آⵃ欽կ
ٖؔٝآ葿ך鿇ⴓָRedux-Sagaַךؿٗ٦ 㹋ꥷחlocalhostח،ؙإأ׃גծ ⰻ鿇דֲ♧䏝ずׄؒٝسه؎ٝز〨ֻկ APIエンドポイント DB React Redux-Saga⹛ַׅ X-Rest-Requestقحت➰♷׃ 㹋ꥷחAPIؒٝسه؎ٝز localhostחぢַג〨ֻ
ブラウザ JSON ؒٝذ؍ذ؍ך《䖤
Redux State of SSR ؟٦غ٦כ鵤ׅ⦼SSRךٖٝتؚٔٝ穠卓הծJSON勴⟝ח״ ג㢌ִזֽלזזְկ 剑ⴱכGetػًٓ٦ة⢪גְָծ 植㖈כقحتחX-Rest-Request: 1鏣㹀ֿׅהד㔐鼘׃גְկ ֮הծأومהPCד鵤ׅⰻ㺁ָ麩ֲךדծ
User-Agentقحتח䩛⹛ד؟٦غ٦ַ䒷ֹ竰ְUserAgent إحزׅկ
Redux Initial state SSRׅהׅדח歗חכStateָٖٝتׁؚٔٝגְ朐䡾זך דծⴱ劍朐䡾ך《䖤כأؗحف׃ְկ
State as JSON ת׆ծ؟٦غ؟؎سדٖٝتؚٔٝ׃穠卓ךReduxךStatehtml חJSONה׃ג㙵鴥דծinitialStateה׃גⵃ欽׃կ
const initialState = JSON.stringify(state);! ! <script type="text/javascript"! dangerouslySetInnerHTML={{! __html: `window.__INITIAL_STATE__
= ${initialState}}`! }} />!
State as JSON 如חծcomponentDidMountךة؎ىؚٝדhistory.stateָ瑞 ⴱ㔐ٖٝتؚٔٝהⴻ㹀׃גծ 植㖈ךstatehistory.replaceדhistory.stateח鏣㹀׃կ
Page1 history Page2 history state Page3 history state state וךل٦آחٓٝر؍ؚٝ׃גhistory.stateָ搀ְل٦آָծ
SPAך饯挿הזل٦آחזկ Page2 history Page1 history state Page3 history state state
React-Router V4 㹋ꥷח؟٦غ؟؎سדוך؝ٝه٦طٝز䲽歗ַׅծ וךAPI〨ַֻ寸חכծ React-Router v3דכmatch⢪ֲ鎸✲כְםְ֮ךָծ React-Router v4דכmatchָ䐖姺ׁגְկ זךד➿חmatchPath⢪ֲկ
import {! matchPath! } from 'react-router';! ! const match =
matchPath("/article/1", {! path: '/articel/:articleId',! exact: true! });! ! if (match) {! console.log(match.params)! // Object { articleId: 1 }! }!
React-Router V4 ׃ծֿך倯岀הـٓؐؠךٕ٦ذ؍ؚٝהNodeJSךٕ٦ذ؍ ؚٝד✳ꅾ盖椚חזג׃תֲךדזהַ׃ְ…
Webpack typescriptד㹋鄲׃ծNodeJS⩎typescriptד㹋鄲׃ְկ ׁחWebpackדcss-modules⢪גְךדծWebpack⢪ זְהSSRָ⹛ַזְկ זךדWebpackדכtargetnodeח䭷㹀ֿׅהדծ__dirname 笝䭯׃אאnode_modules⟃㢩ך؝٦سbundle׃կ
module.exports = { entry: { server: './server/index.ts' }, target: 'node',
externals: /^(?!^\.\.?\/)/, output: { path: `${__dirname}/dist`, filename: "[name].js", libraryTarget: "commonjs2" }, resolve: { extensions: [".js", ".ts"] } }
Watch Webpackדwatch׃גְךָծ♧אךؿ؋؎ָٕ㢌刿ׁ ֽד؟٦غ٦ծؙٓ؎،ٝز⚕倯ָⰋגⱄ؝ٝػ؎ׁٕג礵牞遹 欰♳״ֻזְךהծ SSR遤ֲ鿇ⴓך頾蚚ֽ넝ְךדծSSRֽׁח؟٦غג גفٗإأⴓꨄ׃կ
Requst SSR Response HTML Supervisord Renderingサーバ Renderingサーバ Renderingサーバ Supervisord APIサーバ
APIサーバ APIサーバ
Cache ⽃秪חNginxהAppךחmemcached 䮠דծ $request_uri--$is_mobile ְז䠬 ׄךؗ٦ד⥂㶷׃גⱄⵃ欽կ
Nginx memcached Node $host$request_uri--$is_mobile ؗ٦חٍؗحءُ嗚稊 זֽלٖٝتؚٔٝ x-memcached-keyח memcachedךؗ٦إحز x-memcached-keyقحت ך⦼ؗ٦ח⥂㶷
SEO react-lazyload⢪גְךדծ GoogleװBotך،ؙإأך㜥さכ lazyload㐣תׇזְ穠卓鵤ׅ״ֲ חծ react-lazyloadٓحف׃؝ٝه٦ طٝز⢪կ
public render() {! return !this.props.shouldRenderStatic! && this.props.isMobile ? (! <LazyLoad
{...this.props}>! {this.props.children}! </LazyLoad>! ) : this.props.children;! }!
תה SSRכװםזח؝أزָ䱦ַז֭הְֲ䠬䟝կ 葿ղ孡⢪ֲֿה㢳ְ׃ծ 劤䔲ח䗳銲חזתדכװץֹדכזְկ 暴חؿٗٝزؒٝسך؝٦سָ؟٦غד⹛ֻךדծ䌢ח➙ـٓؐ ؠזךַNodeJSזךַ䠐陎ׅךָ⦜կ ׀幠耮ָ֮הֲ׀ְׂת׃կ