Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
BFF/SSRの話
Search
Yosuke Furukawa
PRO
February 19, 2018
Programming
7.9k
26
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
BFF/SSRの話
Mercari Web / Frontend meetupで話した BFF/SSR の話です。
Yosuke Furukawa
PRO
February 19, 2018
More Decks by Yosuke Furukawa
See All by Yosuke Furukawa
Webの地図
yosuke_furukawa
PRO
6
5.2k
XHTMLが残したもの
yosuke_furukawa
PRO
2
950
jsmini JavaScript Engine を作ってみた話
yosuke_furukawa
PRO
0
450
デザインシステムが必須の時代に
yosuke_furukawa
PRO
2
320
Node.js, Deno, Bun 最新動向とその所感について
yosuke_furukawa
PRO
10
5.4k
Welcome JSConf.jp 2024
yosuke_furukawa
PRO
1
4.9k
tc39 x jsconf.jp Panel Discussion 2024
yosuke_furukawa
PRO
0
380
Removing Corepack
yosuke_furukawa
PRO
9
2k
JavaScript Runtime とはなにか
yosuke_furukawa
PRO
15
3.2k
Other Decks in Programming
See All in Programming
No More NoSuchMethodError
exoego
1
110
Vue Fes Japan の “作る側”に関わってみて
naokihaba
0
170
S3 TablesのIcebergデータに、AIエージェントからアクセスしてみた / 20261016developersio2026joetsu-accessing-iceberg-in-s3tables-via-agent
kasacchiful
PRO
0
190
Apple Intelligence を用いた個人情報誤送信防止、及びユーザーリクエスト体験の改善について
yukiny
0
360
Event is what happens
moro
2
1.2k
残高管理から台帳サービスへの進化
artoy
1
210
機械に任せるテスト、人が見るテスト ⽣成AIで引き直した、運⽤保守フェーズの線引き
dske104
0
200
エージェントを使い続けるためのメタワーク / Meta-work for keeping using the agent
rkaga
4
1.4k
Unity6 URPによる海底をテーマにしたVJシステムの解説 | Unity Shader 完全に理解した 勉強会
gam0022
0
370
月間100万人のサービス刷新で、 技術選定をHonoに振り切った話
yutobara
8
6.8k
Jetpack Compose Mechanisms
skydoves
3
840
ChromeでローカルLLM
ryu1013
0
160
Featured
See All Featured
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.5k
WCS-LA-2024
lcolladotor
0
900
Claude Code のすすめ
schroneko
67
230k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
Information Architects: The Missing Link in Design Systems
soysaucechin
1
1.2k
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
2
6.3k
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
430
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.9k
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
310
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6.1k
My Coaching Mixtape
mlcsv
0
360
How to Talk to Developers About Accessibility
jct
2
590
Transcript
SSR / BFF ʹ͍ͭͯ Mercari Web / Frontend meetup #1
2018/02/19
Twitter: @yosuke_furukawa Github: yosuke-furukawa
/PEFֶԂ࣌ݶΔͷͰօ͞Μ དྷͯͶʂʂʂ
࠷ۙBFFʹ͍ͭͯͷΛ ͱ͋ΔϝσΟΞʹॻ͍ͯΔ
͓ͦΒۙ͘ެ։༧ఆ ʢకʹؒʹ߹͑ʣ
ࠓͷ • BFFೖ • SSRೖ • BFF/SSR࣮ફྫs
Α͋͘Δٙ • BFFͬͯͳΜͷͨΊʹ͍Δͷʁ • SSRͬͯSEOෆཁͳΒཁΒͳ͍Μ͡Όͳ͍ʁ • BFF/SSRͬͯ͘͠ͳ͍ͷʁ
BFFೖ
BFFͱԿ͔ • Backends For Frontends • ϑϩϯτΤϯυͷͨΊͷόοΫΤϯυ(αʔό) ͷ͜ͱ ͜͜ʂ
Q. ͳΜͰBFF͕ඞཁͳͷ͔
Q. ͳΜͰBFF͕ඞཁͳͷ͔ A. 2ͭ͋Δ 1. ৫తͳ 2. ੑೳతͳ
Q. ͳΜͰBFF͕ඞཁͳͷ͔ A. 2ͭ͋Δ 1. ৫తͳ 2. ੑೳతͳ (SSRͷ)
BFFͷ৫తͳ • ͜Ε·ͰͷWebΞϓϦέʔγϣϯ • ҰຕؠͰͰ͖ͨΞϓϦέʔγϣϯ • HTMLςϯϓϨʔτͰදࣔΛߏங • ߋ৽FormͰ
BFFͷ৫తͳ • ঃʑʹͦΕ͚ͩͰճΒͳ͘ͳ͖͍ͬͯͯΔ • Ajax௨৴ͰΠϯλϥΫςΟϒʹ • ϞʔμϧυϥοάΛۦͨ͠ϦονͳΠϯ λϑΣʔεʹ
BFFͷ৫తͳ • ঃʑʹͦΕ͚ͩͰճΒͳ͘ͳ͖͍ͬͯͯΔ • Ajax௨৴ͰΠϯλϥΫςΟϒʹ • ϞʔμϧυϥοάΛۦͨ͠ϦονͳΠϯ λϑΣʔεʹ
ͦΕΛಥ͖ਐΊͨઌʹ͋Δ ҉ࠇͷUI • JSP(Java ͷ HTMLςϯϓϨʔτ)͔ΒJavaScriptΛݺ ͼग़͢ʂʂʂ • JavaScriptͰDOMͷதͰΰϦΰϦͷϩδοΫΛॻ ͘ʂʂʂ
• Ajax௨৴தʹDOMͰΠϯδέʔλग़͍͔ͨ͠Βͬͯ શ෦ͷૢ࡞ͰAjax௨৴தʹΠϯδέʔλग़͢ʂʂʂ
ͦΕΛಥ͖ਐΊͨઌʹ͋Δ ҉ࠇͷUI • JSP(Java ͷ HTMLςϯϓϨʔτ)͔ΒJavaScriptΛ ݺͼग़͢ʂʂʂ • JavaScriptͰDOMͷதͰϩδοΫΛॻ͘ʂʂʂ •
Ajax௨৴தʹDOMͰΠϯδέʔλग़͍͔ͨ͠Βͬ ͯશ෦ͷૢ࡞ͰAjax௨৴தʹΠϯδέʔλग़ ͢ʂʂʂ=>ফ͑ͳ͘ͳΔΠϯδέʔλ
ͦΕΛಥ͖ਐΊͨઌʹ͋Δ ҉ࠇͷUI • JSP(Java ͷ HTMLςϯϓϨʔτ)͔ΒJavaScriptΛ ݺͼग़͢ʂʂʂ • JavaScriptͰDOMͷதͰϩδοΫΛॻ͘ʂʂʂ •
Ajax௨৴தʹDOMͰΠϯδέʔλग़͍͔ͨ͠ Βͬͯશ෦ͷૢ࡞ͰAjax௨৴தʹΠϯδέʔλग़ ͢ʂʂʂ
BFFͷ৫తͳ • ͏͍͍Ճݮʹ GUI (ϖʔδ) Λ࡞ΔॴͱσʔλΛ ཧ͢Δॴ͚͍ͨɻ • WebΞϓϦέʔγϣϯϑϨʔϜϫʔΫ͔ͩΒͱ͍ͬ ͯԿͰΔͷͰͳ͘ɺݖݶΛ͍ͨ͠ɻ
• σʔλΛཧ͢ΔॴόοΫΤϯυͰ࣮ࢪ͍ͨ͠ • GUI(ϖʔδ)Λ࡞ΔॴϑϩϯτΤϯυͰ࣮ࢪ͍ͨ͠
BFFͷ৫తͳ
BFFͷ৫తͳ όοΫΤϯυ ΤϯδχΞσʔλ ͷૢ࡞ɾཧʹूத ͢Δɻ
BFFͷ৫తͳ ϑϩϯτΤϯυ ΤϯδχΞ(6* ͷߏஙʹઐ೦͢Δɻ ओͳࣄ6*69ͷ ্
BFFͷྺ࢙తͳ • ࠷ۙ "BFF" ͱ͍͏໊લ͕͍͚ͭͨͩͰಛʹ৽͍͠Ͱ ͳ͍ɻ • ੲͷΤϯλʔϓϥΠζ࣌͜͏͍͏ΞʔΩςΫνϟ͕ଟ ͔ͬͨ (લલ৬Ͱͦ͏ͩͬͨ)
• HTML͕ࠓ·ͰԿ͠ͳͯ͘ϒϥβ͕উखʹGUIΛද ݱͯͨ͠ͷʹΒ͕SPAͱ͔ͰGUIΛ࠶ఆ͔ٛͩͨ͠͠Β ͏Ұ໊લ͕͍ͭͨ(ؾ͕͢Δ)ɻ
BFFͷྺ࢙తͳ • Chapter 5: Re-Architecting ϞϊϦεతͳΞʔΩςΫνϟͰνʔϜ ͱͯ͠εέʔϧ͠ͳ͍ͱࢥͬͨΒɺϑϩ ϯτΤϯυͱόοΫΤϯυʹ͚Δɺ ΑΓίϯςΫετΛҙࣝͯ͠ϚΠΫϩ αʔϏεԽ͢ΔͷΛݕ౼͢Δ
BFFͷྺ࢙తͳ • Chapter 5: Re-Architecting ϞϊϦεతͳΞʔΩςΫνϟͰνʔϜ ͱͯ͠εέʔϧ͠ͳ͍ͱࢥͬͨΒɺϑϩ ϯτΤϯυͱόοΫΤϯυʹ͚Δɺ ΑΓίϯςΫετΛҙࣝͯ͠ϚΠΫϩ αʔϏεԽ͢ΔͷΛݕ౼͢Δ
ϑϩϯτΤϯυͱόοΫΤϯυʹ͚Δɺ ϚΠΫϩαʔϏεΛҙࣝ͢Δ
BFFͷྺ࢙తͳ • ྺ࢙తʹΞʔΩςΫνϟૄ݁߹ͱີ݁߹Λ ܁Γฦͯ͠༳Ε͍ͯΔɻ • લ·Ͱີ݁߹͕ͩͬͨɺ࠷ۙૄ݁߹ͷ͕ྑ ͘ͳ͖ͬͯͨɻ • ࠓޙͲ͏ͳΔ͔Θ͔Βͳ͍ɺ·ͨີ݁߹ʹ Δ͔͠Εͳ͍͠ɺૄ݁߹ͷ··͔͠Εͳ͍ɻ
SSRೖ
SSRͱ • Server Side Rendering ͷུ • Client Side Ͱ
HTML ΛϨϯμϦϯά͢Δ͜ͱ ΛClient Side RenderingͱݺͿɻͦΕʹର͠ ͯಉ͜͡ͱΛ Server Side Ͱ࣮ࢪ͢Δ͜ͱΛ Server Side Rendering ͱݺͿɻ
Server Side Rendering 4FSWFS 1BHF3FRVFTU $PNQPOFOUT 5FNQMBUFT 'FUDI%BUB %#"1* 3FOEFS)5.-
(FUQBHFQBSUT
Server Side Rendering 4FSWFS 1BHF3FRVFTU $PNQPOFOUT 5FNQMBUFT 'FUDI%BUB %#"1* 3FOEFS)5.-
$MJFOU4JEF 3FOEFSFS $PNQPOFOUT 5FNQMBUFT 3FOEFS)5.-XJUITBNF DMJFOUTFSWFSSFOEFSMPHJD 4FSWFS4JEF 3FOEFSFS (FUQBHFQBSUT
Why we need Server Side Rendering?
SEO
SEO
SEO Ϋϩʔϥ͕+4Λ࣮ߦͰ͖Δͱ ͍͑ɺͦͷ+4͕ͪΌΜͱಈ͘อ ূͳ͍ɻ
SEOॏཁɺͰຊ࣍
First View Performance
ͦͦFirst ViewͱҰޱʹ ݴͬͯछྨ͕͋Δ /BWJHBUJPO4UBSU 'JSTU1BJOU 'JSTU$POUFOUGVM 1BJOU Loading.. 'JSTU.FBOJOHGVM 1BJOU
'JSTU.FBOJOHGVM 1BJOU 7JTVBMMZSFBEZ *NBHF 5JNF5P *OUFSBDUJWF +4MPBEFE *NBHF 'VMMZ-PBEFE BMMSFTPVSDFTBSF MPBEFE *NBHF
First View Performance • SSR ʹ͓͚Δ First View ͷվળͱɺ͜ͷ First
Meaningful Paint ·ͰΛࢦ͢ɻ /BWJHBUJPO4UBSU 'JSTU1BJOU 'JSTU$POUFOUGVM 1BJOU Loading.. 'JSTU.FBOJOHGVM 1BJOU
First View Performance • First Meaningful PaintҎ߱ͷվળService WorkerHTTP2ͳͲผͳΓํ͕͋Δɻ 'JSTU.FBOJOHGVM 1BJOU
7JTVBMMZSFBEZ *NBHF 5JNF5P *OUFSBDUJWF +4MPBEFE *NBHF 'VMMZ-PBEFE BMMSFTPVSDFTBSF MPBEFE *NBHF
Client Side Rendering ͷΈͰͷಈ͖
Client Side Rendering ͷΈͷ ߹ • First Meaningful Paint ͱ
Time To Interact ͷ λΠϛϯά͕΄ͱΜͲಉ͡ɻ 'JSTU.FBOJOHGVM1BJOU 5JNF5P*OUFSBDUJWF +4MPBEFE 'JSTU$POUFOUGVM 1BJOU Loading..
Client Side Rendering ͷΈͷ ߹ • ݴ͍͑ΔͱɺFirst Contentful Paint͔ΒFirst Meaningful
Paint ·Ͱ͕͘ͳΔɻ 'JSTU.FBOJOHGVM1BJOU 5JNF5P*OUFSBDUJWF +4MPBEFE 'JSTU$POUFOUGVM 1BJOU Loading..
Client Side Rendering ͷΈͷ ߹ • ݴ͍͑ΔͱɺFirst Contentful Paint͔ΒFirst Meaningful
Paint ·Ͱ͕͘ͳΔɻ 'JSTU.FBOJOHGVM1BJOU 5JNF5P*OUFSBDUJWF +4MPBEFE 'JSTU$POUFOUGVM 1BJOU Loading.. Ϣʔβʔݟ͔͑ͯΒૢ࡞͢Δ 'JSTU.FBOJOHGVM1BJOU͕ग़͔ͯΒ*OUFSBDU ͢Δ ͷͰɺ͜ͷ$MJFOU4JEF3FOEFSJOH͚ͩͰ࣌ؒతʹແବ͕ଟ͍ɻ
ͦ͜Ͱ Server Side Rendering
/BWJHBUJPO4UBSU 'JSTU1BJOU 'JSTU$POUFOUGVM 1BJOU Loading.. 'JSTU.FBOJOHGVM 1BJOU ࠷ॳ͔ΒσʔλΛຒΊࠐΜͩঢ়ଶͰ)5.-ʹ͢Δ ʢ4FSWFS4JEF3FOEFSJOHʣ
ʮBFFΛಋೖ͢Δʯͱ͍͏࣌ ʹʮSSRʯ·Ͱηοτͷํ͕ ϏδωεతͳϝϦοτ(ੑೳɺ SEO)આ໌͍͢͠ɻ
BFF/SSR࣮ફྫ
BFF/SSR࣮ફྫ • ฐࣾͷϘΠϥʔϓϨʔτΛߏங͠ɺͦΕΛల։͢ΔܗͰ֤։ ൃ͔ΒͬͯΒ͍ͬͯΔ • bookingtable(ϨετϥϯݕࡧαΠτ)Ͱͷ࣮ફ (2016/11~) • raico(SNS)Ͱͷ࣮ફ (2016/12
~) • coshigoto(ΞϯέʔτΞϓϦ)Ͱͷ࣮ફ (2017/08 ~) • AirShift(εέδϡʔϧཧΞϓϦ)Ͱͷ࣮ફ (2017/09 ~)
BFF/SSR࣮ફྫ • ฐࣾͷϘΠϥʔϓϨʔτΛߏங͠ɺͦΕΛల։͢ΔܗͰ֤։ ൃ͔ΒͬͯΒ͍ͬͯΔ • bookingtable(ϨετϥϯݕࡧαΠτ)Ͱͷ࣮ફ (2016/11~) • raico(SNS)Ͱͷ࣮ફ (2016/12
~) • coshigoto(ΞϯέʔτΞϓϦ)Ͱͷ࣮ફ (2017/08 ~) • AirShift(εέδϡʔϧཧΞϓϦ)Ͱͷ࣮ફ (2017/09 ~) ࣮ફճଟɺࠓޙ͍͔ͭ͘࠾༻༧ఆ
ฐࣾϘΠϥʔϓϨʔτ
redux-protoͱݺΕΔϘΠ ϥʔϓϨʔτΛ࡞ͬͯΔ • View: React • State Management: Redux •
Component Management: Atomic Design • Redux Middleware: redux-effects, redux-async- loader, etc • SSR ready, Service Worker ready, AMP not yet
redux-protoͱݺΕΔϘΠ ϥʔϓϨʔτΛ࡞ͬͯΔ • View: React • State Management: Redux •
Component Management: Atomic Design • Redux Middleware: redux-effects, redux-async- loader, etc • SSR ready, Service Worker ready, AMP not yet ϦΫϧʔτͷ-JWJOH"QQ4UBOEBSE ͱͯ͠։ൃத
redux-protoͱݺΕΔϘΠ ϥʔϓϨʔτΛ࡞ͬͯΔ • View: React • State Management: Redux •
Component Management: Atomic Design • Redux Middleware: redux-effects, redux-async- loader, etc • SSR ready, Service Worker ready, AMP not yet ۙެ։͢Δʂʂʂʂ ͔
ฐࣾϘΠϥʔϓϨʔτ ͪΐͬͱհ (React͔Δਓ͚)
ιʔείʔυϨΠΞτ . !"" client // Client ͰͷΈ࣮ࢪ͢Δίʔυ܈ɺͪͳΈʹຊʹϑΝΠϧ͔͠ͳ͍ɻ # !"" analytics
// Google Analytics ͷղੳπʔϧ # $"" vendor // ֎෦ϕϯμʔͰClientͰͷΈ࣮ࢪ͢Δͷ !"" server // Server ͰͷΈ࣮ࢪ͢Δίʔυ܈ɻ # !"" components // SSRͷ࣌ͷίϯϙʔωϯτ # !"" configs // ίϯϑΟάϑΝΠϧ܈ # !"" libs // ·ͩnpmʹͳͬͯͳ͍ϥΠϒϥϦ܈ # !"" middlewares // SSRΛ࣮͍ͯ͠ΔίΞͷ෦ # $"" services // APIͷ·ͱΊΛߦ͍ͬͯΔαʔϏε !"" shared # !"" components // atoms, molecules, organisms ͱ֊ʹͳͬͯΔɺSSR/CSR྆ํͰ࣮ࢪ # !"" redux // actions/reducersͰ͚ͯͳͯ͘ɺducksܗࣜͷϞδϡʔϧʹͳͬͯΔ # !"" routes // ϧʔλʔͷఆٛɺ͜͜Ͱ Code Splitting ͷઃఆߦ͍ͬͯΔ # !"" utils // ࡶଟͳͷ # $"" validators // Validation܈ !"" sw // Service Worker ϑΥϧμ $"" webpack // Webpack ϑΥϧμ
Atom Component export default compose( onlyUpdateForPropTypes, // PropTypesʹॻ͍ͨͷ͕มߋ͞Ε͚ͨ࣌ͩrendering͢Δ setPropTypes({ //
PropTypesΛఆٛ loading: PropTypes.bool.isRequired, }), )(function Indicator(props) { const { loading } = props; if (!loading) { return null; } return ( <div className={local(‘loader’)}></div> ); });
Flowͷ߹ // @flow import React from 'react'; import { compose,
onlyUpdateForKeys } from 'recompose'; export default compose( onlyUpdateForKeys(), // FlowTypeͷ߹babel-pluginͰܕใΛύʔεͯ͠উ खʹshouldComponentUpdateΛ࣮ࢪ͢ΔϓϥάΠϯΛೖΕͯΔɻ )(function Foo(props: { foo: string, bar: number }) { const { foo, bar } = props; return ( <div>{foo}-{bar}</div> ); }); https://github.com/recruit-tech/babel-plugin-flow- onlyupdateforkeys
Flowͷ߹ // @flow import React from 'react'; import { compose,
onlyUpdateForKeys } from 'recompose'; export default compose( onlyUpdateForKeys(), // FlowTypeͷ߹babel-pluginͰܕใΛύʔεͯ͠উ खʹshouldComponentUpdateΛ࣮ࢪ͢ΔϓϥάΠϯΛೖΕͯΔɻ )(function Foo(props: { foo: string, bar: number }) { const { foo, bar } = props; return ( <div>{foo}-{bar}</div> ); }); ܕใΛݩʹνϡʔχϯά͢Δ Έ͕ೖͬͯΔ https://github.com/recruit-tech/babel-plugin-flow- onlyupdateforkeys
Code Splitting using SSR import createUniversalComponent from ‘./createUniversalComponent’; const chunkName
= ‘salon’; export function loadSalon(_, cb) { createUniversalComponent( () => import(/* webpackChunkName: “salon” */ ‘../components/organisms/Salon’), () => require.resolveWeak(‘../components/organisms/Salon’), chunkName, ).then((result) => cb(null, result), cb); } export function loadSalonForm(_, cb) { createUniversalComponent( () => import(/* webpackChunkName: “salon” */ ‘../components/organisms/SalonForm’), () => require.resolveWeak(‘../components/organisms/SalonForm’), chunkName, ).then((result) => cb(null, result), cb); } https://github.com/faceyspacey/react-universal- component
Code Splitting using SSR import createUniversalComponent from ‘./createUniversalComponent’; const chunkName
= ‘salon’; export function loadSalon(_, cb) { createUniversalComponent( () => import(/* webpackChunkName: “salon” */ ‘../components/organisms/Salon’), () => require.resolveWeak(‘../components/organisms/Salon’), chunkName, ).then((result) => cb(null, result), cb); } export function loadSalonForm(_, cb) { createUniversalComponent( () => import(/* webpackChunkName: “salon” */ ‘../components/organisms/SalonForm’), () => require.resolveWeak(‘../components/organisms/SalonForm’), chunkName, ).then((result) => cb(null, result), cb); } https://github.com/faceyspacey/react-universal- component $PEF4QMJUͭͭ͠443ͷ࣌ී ௨ʹ+4$44ΛGFUDI͢ΔΈ
Α͋͘Δٙ • BFFͬͯͳΜͷͨΊʹ͍Δͷʁ => ݖݶͷͱ։ൃͷ͢͠͞ • SSRͬͯSEOෆཁͳΒཁΒͳ͍Μ͡Όͳ͍ʁ => No, First
Meaningful PaintΛ࠷దԽ͢ΔͨΊʹඞཁ • BFF/SSRͬͯ͘͠ͳ͍ͷʁ => Partially Yes, ࠷ॳͷઃܭ͍͠ɻઃܭతͳ͠͞ΛΓӽ͑ Ε࣮͘͠ͳ͍ɻ͞Βʹ࠷ۙNext.jsͱ͔Nuxt.jsͱ͔ग़ͯ Δ͔Βঃʑʹ͘͠ͳ͘ͳ͖ͬͯͯΔ͔ɻ
Thank you