Upgrade to Pro — share decks privately, control downloads, hide ads and more …

BFF/SSRの話

 BFF/SSRの話

Mercari Web / Frontend meetupで話した BFF/SSR の話です。

Yosuke Furukawa

February 19, 2018
Tweet

More Decks by Yosuke Furukawa

Other Decks in Programming

Transcript

  1. ͦΕΛಥ͖ਐΊͨઌʹ͋Δ ҉ࠇͷUI • JSP(Java ͷ HTMLςϯϓϨʔτ)͔ΒJavaScriptΛݺ ͼग़͢ʂʂʂ • JavaScriptͰDOMͷதͰΰϦΰϦͷϩδοΫΛॻ ͘ʂʂʂ

    • Ajax௨৴தʹDOMͰΠϯδέʔλग़͍͔ͨ͠Βͬͯ શ෦ͷૢ࡞ͰAjax௨৴தʹΠϯδέʔλग़͢ʂʂʂ
  2. ͦΕΛಥ͖ਐΊͨઌʹ͋Δ ҉ࠇͷUI • JSP(Java ͷ HTMLςϯϓϨʔτ)͔ΒJavaScriptΛ ݺͼग़͢ʂʂʂ • JavaScriptͰDOMͷதͰϩδοΫΛॻ͘ʂʂʂ •

    Ajax௨৴தʹDOMͰΠϯδέʔλग़͍͔ͨ͠Βͬ ͯશ෦ͷૢ࡞ͰAjax௨৴தʹΠϯδέʔλग़ ͢ʂʂʂ=>ফ͑ͳ͘ͳΔΠϯδέʔλ΁
  3. ͦΕΛಥ͖ਐΊͨઌʹ͋Δ ҉ࠇͷUI • JSP(Java ͷ HTMLςϯϓϨʔτ)͔ΒJavaScriptΛ ݺͼग़͢ʂʂʂ • JavaScriptͰDOMͷதͰϩδοΫΛॻ͘ʂʂʂ •

    Ajax௨৴தʹDOMͰΠϯδέʔλग़͍͔ͨ͠ Βͬͯશ෦ͷૢ࡞ͰAjax௨৴தʹΠϯδέʔλग़ ͢ʂʂʂ
  4. BFFͷྺ࢙తͳ࿩ • ࠷ۙ "BFF" ͱ͍͏໊લ͕͍͚ͭͨͩͰಛʹ৽͍͠࿩Ͱ͸ ͳ͍ɻ • ੲͷΤϯλʔϓϥΠζ࣌୅͸͜͏͍͏ΞʔΩςΫνϟ͕ଟ ͔ͬͨ (๻΋લલ৬Ͱ͸ͦ͏ͩͬͨ)

    • HTML͕ࠓ·ͰԿ΋͠ͳͯ͘΋ϒϥ΢β͕উखʹGUIΛද ݱͯͨ͠ͷʹ๻Β͕SPAͱ͔ͰGUIΛ࠶ఆ͔ٛͩͨ͠͠Β ΋͏Ұ౓໊લ͕͍ͭͨ(ؾ͕͢Δ)ɻ
  5. SSRͱ͸ • Server Side Rendering ͷུ • Client Side Ͱ

    HTML ΛϨϯμϦϯά͢Δ͜ͱ ΛClient Side RenderingͱݺͿɻͦΕʹର͠ ͯಉ͜͡ͱΛ Server Side Ͱ΋࣮ࢪ͢Δ͜ͱΛ Server Side Rendering ͱݺͿɻ
  6. Server Side Rendering 4FSWFS 1BHF3FRVFTU $PNQPOFOUT 5FNQMBUFT 'FUDI%BUB %#"1* 3FOEFS)5.-

    $MJFOU4JEF 3FOEFSFS $PNQPOFOUT 5FNQMBUFT 3FOEFS)5.-XJUITBNF DMJFOUTFSWFSSFOEFSMPHJD 4FSWFS4JEF 3FOEFSFS (FUQBHFQBSUT
  7. SEO

  8. SEO

  9. ͦ΋ͦ΋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
  10. First View Performance • SSR ʹ͓͚Δ First View ͷվળͱ͸ɺ͜ͷ First

    Meaningful Paint ·ͰΛࢦ͢ɻ /BWJHBUJPO4UBSU 'JSTU1BJOU 'JSTU$POUFOUGVM 1BJOU Loading.. 'JSTU.FBOJOHGVM 1BJOU
  11. First View Performance • First Meaningful PaintҎ߱ͷվળ͸Service Worker΍HTTP2ͳͲผͳ΍Γํ͕͋Δɻ 'JSTU.FBOJOHGVM 1BJOU

    7JTVBMMZSFBEZ *NBHF 5JNF5P *OUFSBDUJWF +4MPBEFE *NBHF 'VMMZ-PBEFE BMMSFTPVSDFTBSF MPBEFE *NBHF
  12. Client Side Rendering ͷΈͷ ৔߹ • First Meaningful Paint ͱ

    Time To Interact ͷ λΠϛϯά͕΄ͱΜͲಉ͡ɻ 'JSTU.FBOJOHGVM1BJOU 5JNF5P*OUFSBDUJWF +4MPBEFE 'JSTU$POUFOUGVM 1BJOU Loading..
  13. Client Side Rendering ͷΈͷ ৔߹ • ݴ͍׵͑ΔͱɺFirst Contentful Paint͔ΒFirst Meaningful

    Paint ·Ͱ͕௕͘ͳΔɻ 'JSTU.FBOJOHGVM1BJOU 5JNF5P*OUFSBDUJWF +4MPBEFE 'JSTU$POUFOUGVM 1BJOU Loading..
  14. Client Side Rendering ͷΈͷ ৔߹ • ݴ͍׵͑ΔͱɺFirst Contentful Paint͔ΒFirst Meaningful

    Paint ·Ͱ͕௕͘ͳΔɻ 'JSTU.FBOJOHGVM1BJOU 5JNF5P*OUFSBDUJWF +4MPBEFE 'JSTU$POUFOUGVM 1BJOU Loading.. Ϣʔβʔ͸ݟ͔͑ͯΒૢ࡞͢Δ 'JSTU.FBOJOHGVM1BJOU͕ग़͔ͯΒ*OUFSBDU ͢Δ ͷͰɺ͜ͷ$MJFOU4JEF3FOEFSJOH͚ͩͰ͸࣌ؒతʹແବ͕ଟ͍ɻ
  15. BFF/SSR࣮ફྫ • ฐࣾͷϘΠϥʔϓϨʔτΛߏங͠ɺͦΕΛల։͢ΔܗͰ֤։ ൃ͔Β࢖ͬͯ΋Β͍ͬͯΔ • bookingtable(ϨετϥϯݕࡧαΠτ)Ͱͷ࣮ફ (2016/11~) • raico(SNS)Ͱͷ࣮ફ (2016/12

    ~) • coshigoto(ΞϯέʔτΞϓϦ)Ͱͷ࣮ફ (2017/08 ~) • AirShift(εέδϡʔϧ؅ཧΞϓϦ)Ͱͷ࣮ફ (2017/09 ~) ࣮ફճ਺ଟ਺ɺࠓޙ΋͍͔ͭ͘࠾༻༧ఆ
  16. 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
  17. 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 ͱͯ͠։ൃத
  18. 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 ۙ೔ެ։͢Δʂʂʂʂ ͔΋
  19. ιʔείʔυϨΠΞ΢τ . !"" 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 ϑΥϧμ
  20. 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> ); });
  21. 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
  22. 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
  23. 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
  24. 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͢Δ࢓૊Έ
  25. Α͋͘Δٙ໰ • BFFͬͯͳΜͷͨΊʹ͍Δͷʁ
 => ݖݶͷ෼཭ͱ։ൃͷ͠΍͢͞ • SSRͬͯSEOෆཁͳΒཁΒͳ͍Μ͡Όͳ͍ʁ
 => No, First

    Meaningful PaintΛ࠷దԽ͢ΔͨΊʹ͸ඞཁ • BFF/SSRͬͯ೉͘͠ͳ͍ͷʁ
 => Partially Yes, ࠷ॳͷઃܭ͸೉͍͠ɻઃܭతͳ೉͠͞Λ৐Γӽ͑ Ε͹࣮૷͸೉͘͠ͳ͍ɻ͞Βʹ࠷ۙ͸Next.jsͱ͔Nuxt.jsͱ͔ग़ͯ Δ͔Βঃʑʹ೉͘͠ͳ͘ͳ͖ͬͯͯΔ͔΋ɻ