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

Common Distribution Technology that Supports th...

Common Distribution Technology that Supports the Frontend of Yahoo! JAPAN Shopping

Hiroaki Konaka (Yahoo! JAPAN / Production Division 1, Shopping Service Group, Commerce Group / Frontend Engineer)
Hisashi Tanaka (Yahoo! JAPAN / Production Division 1, Shopping Service Group, Commerce Group / Frontend Engineer)

https://tech-verse.me/ja/sessions/151
https://tech-verse.me/en/sessions/151
https://tech-verse.me/ko/sessions/151

Tech-Verse2022

November 18, 2022
Tweet

More Decks by Tech-Verse2022

Other Decks in Technology

Transcript

  1. Agenda - Circumstances leading up to the birth of the

    common UI distribution service - Technology that supports the common UI distribution service
  2. Agenda - Circumstances leading up to the birth of the

    common UI distribution service - Technology that supports the common UI distribution service
  3. The Yahoo Shopping Screen and the Development Team Top Search

    Product Details Cart Review Contact us Products Campaign Existence of Various Screens and Presence of Various Development Teams
  4. Example Top Search Product Details HyperLink HyperLink The Top Team

    Node.js SearchTeam Node.js Product Details Team PHP
  5. Example Top Search Product Details HyperLink HyperLink The Top Team

    Node.js SearchTeam Node.js Product Details Team PHP
  6. This part is common UI Shopping Convenient acquisition with ID

    Login Open [Important] Yahoo! Shopping and PayPay Mall will be integrated on October 12th What are you looking for? Filter Cart Favorites H
  7. If you want to modify the common UI There are

    many people involved.. To whom should we explain
  8. If you want to modify the common UI There are

    many people involved.. To whom should we explain At no time is everyone free..
  9. If you want to modify the common UI There are

    many people involved.. To whom should we explain At no time is everyone free.. The start time for development varies
  10. If you want to modify the common UI There are

    many people involved.. To whom should we explain At no time is everyone free.. The start time for development varies It becomes difficult to align the release time.
  11. If you want to modify the common UI There are

    many people involved.. To whom should we explain At no time is everyone free.. The start time for development varies It becomes difficult to align the release time. It is also possible that there was a team that was overlooked..
  12. If you want to modify the common UI There are

    many people involved.. To whom should we explain At no time is everyone free.. The start time for development varies It becomes difficult to align the release time. It is also possible that there was a team that was overlooked.. There is something that is subtly different..
  13. In the midst of this, a company-wide large-scale refactoring of

    the system was ordered At the same time, I reviewed the front end too, and built a common UI distribution system for shopping
  14. ptah-commons Though it is not UI, it is logic that

    is closely related to UI construction and distributed in library format ・Acquisition and processing of user information ・Login judgment ptah-v2 Distribution of UI common to almost all screens module-service Common navigation module used on multiple screens, etc. Three pillars of the common UI distribution system (Ptah)
  15. ptah-commons Though it is not UI, it is logic that

    is closely related to UI construction and distributed in library format ・Acquisition and processing of user information ・Login judgment ptah-v2 Distribution of UI common to almost all screens module-service Common navigation module used on multiple screens, etc. Three pillars of the common UI distribution system (Ptah)
  16. ptah-commons Though it is not UI, it is logic that

    is closely related to UI construction and distributed in library format ・Acquisition and processing of user information ・Login judgment ptah-v2 Distribution of UI common to almost all screens module-service Common navigation module used on multiple screens, etc. Three pillars of the common UI distribution system (Ptah)
  17. ptah-commons Though it is not UI, it is logic that

    is closely related to UI construction and distributed in library format ・Acquisition and processing of user information ・Login judgment ptah-v2 Distribution of UI common to almost all screens module-service Common navigation module used on multiple screens, etc. Three pillars of the common UI distribution system (Ptah)
  18. ptah-commons Though it is not UI, it is logic that

    is closely related to UI construction and distributed in library format ・Acquisition and processing of user information ・Login judgment ptah-v2 Distribution of UI common to almost all screens module-service Common navigation module used on multiple screens, etc. Three pillars of the common UI distribution system (Ptah)
  19. What we would like to achieve with Ptah-v2 UX will

    not be compromised Unified layout and specifications Using React Front language/FW will not be restricted Without any work at the front it can be changed Reduction of man-hours
  20. What we would like to achieve with Ptah-v2 UX will

    not be compromised Unified layout and specifications Using React Front language/FW will not be restricted Without any work at the front it can be changed Reduction of man-hours
  21. What we would like to achieve with Ptah-v2 UX will

    not be compromised Unified layout and specifications Using React Front language/FW will not be restricted Without any work at the front it can be changed Reduction of man-hours
  22. What we would like to achieve with Ptah-v2 UX will

    not be compromised Unified layout and specifications Using React Front language/FW will not be restricted Without any work at the front it can be changed Reduction of man-hours
  23. What we would like to achieve with Ptah-v2 UX will

    not be compromised Unified layout and specifications Using React Front language/FW will not be restricted Without any work at the front it can be changed Reduction of man-hours
  24. What we would like to achieve with Ptah-v2 UX will

    not be compromised Unified layout and specifications Using React Front language/FW will not be restricted Without any work at the front it can be changed Reduction of man-hours
  25. Important matters UX will not be compromised Unified layout and

    specifications Using React Front language/FW will not be restricted Reduction of man-hours Without any work at the front it can be changed
  26. • Can be changed in a phased manner Micro Frontends

    What is? React (Team A) Vue (Team B) Web Components (Team C) • Simple and loosely coupled • Can be deployed independently
  27. The existing structure Top Search Product Details HyperLink HyperLink The

    Top Team Node.js SearchTeam Node.js Product Details Team PHP
  28. The existing structure Top Search Product Details HyperLink HyperLink The

    Top Team Node.js SearchTeam Node.js Product Details Team PHP
  29. The existing structure+common distribution Top Search Product Details Common distribution

    team Node.js The Top Team Node.js SearchTeam Node.js Product Details Team PHP
  30. Important matters UX will not be compromised Unified layout and

    specifications Using React Front language/FW will not be restricted Without any work at the front it can be changed Reduction of man-hours ✔ ✔
  31. Important matters UX will not be compromised Unified layout and

    specifications Using React Front language/FW will not be restricted Without any work at the front it can be changed Reduction of man-hours ✔ ✔ ✔
  32. Important matters UX will not be compromised Unified layout and

    specifications Using React Front language/FW will not be restricted Without any work at the front it can be changed Reduction of man-hours ✔ ✔ ✔ ✔ ✔
  33. Important matters UX will not be compromised Unified layout and

    specifications Using React Front language/FW will not be restricted Without any work at the front it can be changed Reduction of man-hours ✔ ✔ ✔ ✔ ✔
  34. common UI This part is in MicroFrontends Using React Shopping

    Convenient acquisition with ID Login Open [Important] Yahoo! Shopping and PayPay Mall will be integrated on October 12th What are you looking for? Filter Cart Favorites H
  35. Agenda - Circumstances leading up to the birth of the

    common UI distribution service - Technology that supports the common UI distribution service
  36. Front System Configuration CDN Browser 2. Get JS/CSS 3’. Get

    the content data 専用BFF 3. Render React component 1. Get the page HTML Backend Dedicated BFF
  37. Front <html> <head> <!– Common CSS --> <link rel="stylesheet" href="https://xxx/style.css"

    /> <!– Core JS --> <script src="https://xxx/core.js"></script> <!– Initialization process --> <script> (function () { xxx.yyy.zzz.init({…}); })(); </script> </head> <body> <!– CustomElement tag for UI components --> <shp-header hoge="fuga"></shp-header> <!– JS for UI components --> <script async src="https://xxx/1.0/shp-header.js"></script> </body> </html> Page HTML
  38. Front ⎯ Common CSS loading Add link tag <html> <head>

    <!– Common CSS --> <link rel="stylesheet" href="https://xxx/style.css" /> <!– Core JS --> <script src="https://xxx/core.js"></script> <!– Initialization process --> <script> (function () { xxx.yyy.zzz.init({…}); })(); </script> </head> <body> <!– CustomElement tag for UI components --> <shp-header hoge="fuga"></shp-header> <!– JS for UI components --> <script async src="https://xxx/1.0/shp-header.js"></script> </body> </html> Page HTML
  39. Front Add script tags ⎯ Common CSS loading ⎯ Loading

    Ptah’s core JS ⎯ Initialization process Add link tag <html> <head> <!– Common CSS --> <link rel="stylesheet" href="https://xxx/style.css" /> <!– Core JS --> <script src="https://xxx/core.js"></script> <!– Initialization process --> <script> (function () { xxx.yyy.zzz.init({…}); })(); </script> </head> <body> <!– CustomElement tag for UI components --> <shp-header hoge="fuga"></shp-header> <!– JS for UI components --> <script async src="https://xxx/1.0/shp-header.js"></script> </body> </html> Page HTML
  40. Front Add script tags Add tags for UI components ⎯

    Common CSS loading ⎯ Loading Ptah’s core JS ⎯ Initialization process ⎯ Placement of CustomElement tag ⎯ Loading JS for UI Components ⎯ Specify parameters with attributes Add link tag <html> <head> <!– Common CSS --> <link rel="stylesheet" href="https://xxx/style.css" /> <!– Core JS --> <script src="https://xxx/core.js"></script> <!– Initialization process --> <script> (function () { xxx.yyy.zzz.init({…}); })(); </script> </head> <body> <!– CustomElement tag for UI components --> <shp-header hoge="fuga"></shp-header> <!– JS for UI components --> <script async src="https://xxx/1.0/shp-header.js"></script> </body> </html> Page HTML
  41. Front Add script tags Add tags for UI components ⎯

    Common CSS loading ⎯ Loading Ptah’s core JS ⎯ Initialization process ⎯ Placement of CustomElement tag ⎯ Loading JS for UI Components ⎯ Specify parameters with attributes Add link tag <html> <head> <!– Common CSS --> <link rel="stylesheet" href="https://xxx/style.css" /> <!– Core JS --> <script src="https://xxx/core.js"></script> <!– Initialization process --> <script> (function () { xxx.yyy.zzz.init({…}); })(); </script> </head> <body> <!– CustomElement tag for UI components --> <shp-header hoge="fuga"></shp-header> <!– JS for UI components --> <script async src="https://xxx/1.0/shp-header.js"></script> </body> </html> Page HTML
  42. Browser Render React component Get the content data Load JS/CSS

    // CustomElementClass Definition class Element extends HTMLElement { connectedCallback() { // Render React components with lifecycle callbacks const container = document.createElement('div'); const props = { hoge: this.getAttribute('hoge') }; const component = React.createElement(ShpHeader, props); ReactDOM.render(component, container); this.appendChild(container); } }; // Add CustomElement customElements.define('shp-header’, Element); CustomElement → React component
  43. Browser Render React component Get the content data Load JS/CSS

    // CustomElementClass Definition class Element extends HTMLElement { connectedCallback() { // Render React components with lifecycle callbacks const container = document.createElement('div'); const props = { hoge: this.getAttribute('hoge') }; const component = React.createElement(ShpHeader, props); ReactDOM.render(component, container); this.appendChild(container); } }; // Add CustomElement customElements.define('shp-header’, Element); CustomElement → React component
  44. Browser Render React component Get the content data Load JS/CSS

    // CustomElementClass Definition class Element extends HTMLElement { connectedCallback() { // Render React components with lifecycle callbacks const container = document.createElement('div'); const props = { hoge: this.getAttribute('hoge') }; const component = React.createElement(ShpHeader, props); ReactDOM.render(component, container); this.appendChild(container); } }; // Add CustomElement customElements.define('shp-header’, Element); CustomElement → React component
  45. Browser Render React component Get the content data Load JS/CSS

    // CustomElementClass Definition class Element extends HTMLElement { connectedCallback() { // Render React components with lifecycle callbacks const container = document.createElement('div'); const props = { hoge: this.getAttribute('hoge') }; const component = React.createElement(ShpHeader, props); ReactDOM.render(component, container); this.appendChild(container); } }; // Add CustomElement customElements.define('shp-header’, Element); CustomElement → React component
  46. Browser Render React component Get the content data Load JS/CSS

    // CustomElementClass Definition class Element extends HTMLElement { connectedCallback() { // Render React components with lifecycle callbacks const container = document.createElement('div'); const props = { hoge: this.getAttribute('hoge') }; const component = React.createElement(ShpHeader, props); ReactDOM.render(component, container); this.appendChild(container); } }; // Add CustomElement customElements.define('shp-header’, Element); CustomElement → React component
  47. Browser Render React component Get the content data Load JS/CSS

    // CustomElementClass Definition class Element extends HTMLElement { connectedCallback() { // Render React components with lifecycle callbacks const container = document.createElement('div'); const props = { hoge: this.getAttribute('hoge') }; const component = React.createElement(ShpHeader, props); ReactDOM.render(component, container); this.appendChild(container); } }; // Add CustomElement customElements.define('shp-header’, Element); CustomElement → React component
  48. Browser Render React component Get the content data Load JS/CSS

    // CustomElementClass Definition class Element extends HTMLElement { connectedCallback() { // Render React components with lifecycle callbacks const container = document.createElement('div'); const props = { hoge: this.getAttribute('hoge') }; const component = React.createElement(ShpHeader, props); ReactDOM.render(component, container); this.appendChild(container); } }; // Add CustomElement customElements.define('shp-header’, Element); CustomElement → React component
  49. Important matters UX will not be compromised Unified layout and

    specifications Using React Front language/FW will not be restricted Without any work at the front it can be changed Reduction of man-hours ✔ ✔ ✔ ✔ ✔ → need SSR Layout shift
  50. Front System Configuration CDN Browser 2. Get JS/CSS 3’. Get

    the content data 専用BFF 3. Render React component 1. Get the page HTML SSR API 1’. Get HTML fragment SSR with the same React component as 3 Backend Dedicated BFF
  51. Front Add a request to the SSR API and paste

    the HTML fragment/initialization data <!-- Common CSS --> <link rel="stylesheet" href="https://xxx/style.css" /> <!-- Core JS --> <script src="https://xxx/core.js"></script> <!– initialization process --> <script> (function () { xxx.yyy.zzz.init({…}); })(); </script> <!– paste the initialization data --> <script id="xxx-json" type="application/json"> [data initialization in SSR] </script> </head> <body> <!-- CustomElement tag for UI components --> <shp-header><div>[SSR HTML string]</div></shp-header> <!-- JS for UI components --> <script async src="https://xxx/1.0/shp-header.js"></script> Page HTML // What was specified in the attribute of CustomElement const params = { shpHeader: { props: { hoge: 'fuga' } } }; SSR API request parameters
  52. Front Add a request to the SSR API and paste

    the HTML fragment/initialization data <!-- Common CSS --> <link rel="stylesheet" href="https://xxx/style.css" /> <!-- Core JS --> <script src="https://xxx/core.js"></script> <!– initialization process --> <script> (function () { xxx.yyy.zzz.init({…}); })(); </script> <!– paste the initialization data --> <script id="xxx-json" type="application/json"> [data initialization in SSR] </script> </head> <body> <!-- CustomElement tag for UI components --> <shp-header><div>[SSR HTML string]</div></shp-header> <!-- JS for UI components --> <script async src="https://xxx/1.0/shp-header.js"></script> Page HTML // What was specified in the attribute of CustomElement const params = { shpHeader: { props: { hoge: 'fuga' } } }; SSR API request parameters
  53. Front Add a request to the SSR API and paste

    the HTML fragment/initialization data <!-- Common CSS --> <link rel="stylesheet" href="https://xxx/style.css" /> <!-- Core JS --> <script src="https://xxx/core.js"></script> <!– initialization process --> <script> (function () { xxx.yyy.zzz.init({…}); })(); </script> <!– paste the initialization data --> <script id="xxx-json" type="application/json"> [data initialization in SSR] </script> </head> <body> <!-- CustomElement tag for UI components --> <shp-header><div>[SSR HTML string]</div></shp-header> <!-- JS for UI components --> <script async src="https://xxx/1.0/shp-header.js"></script> Page HTML // What was specified in the attribute of CustomElement const params = { shpHeader: { props: { hoge: 'fuga' } } }; SSR API request parameters
  54. Browser ... // Initialization data includes parameters and content data

    used during SSR const jsonTag = document.getElementById('xxx-json’); const initialData = JSON.parse(jsonTag.textContent); const props = { ...initialData.shpHeader?.props, initialData }; //For operation without JS version update, hydrate is not used // hydrate is based on the assumption that the DOM structure is the same for SSR and CSR const container = this.children[0]; container.innerHTML = ''; ReactDOM.render( React.createElement(ShpHeader, props), container); ... ... const container = document.createElement('div’); const props = { hoge: this.getAttribute('hoge') }; const component = React.createElement(ShpHeader, props); ReactDOM.render(component, container); this.appendChild(container); ... CSR Isomorphic Reactコンポーネント描画方式の変更
  55. Browser ... // Initialization data includes parameters and content data

    used during SSR const jsonTag = document.getElementById('xxx-json’); const initialData = JSON.parse(jsonTag.textContent); const props = { ...initialData.shpHeader?.props, initialData }; //For operation without JS version update, hydrate is not used // hydrate is based on the assumption that the DOM structure is the same for SSR and CSR const container = this.children[0]; container.innerHTML = ''; ReactDOM.render( React.createElement(ShpHeader, props), container); ... ... const container = document.createElement('div’); const props = { hoge: this.getAttribute('hoge') }; const component = React.createElement(ShpHeader, props); ReactDOM.render(component, container); this.appendChild(container); ... CSR Isomorphic Reactコンポーネント描画方式の変更
  56. Browser ... // Initialization data includes parameters and content data

    used during SSR const jsonTag = document.getElementById('xxx-json’); const initialData = JSON.parse(jsonTag.textContent); const props = { ...initialData.shpHeader?.props, initialData }; //For operation without JS version update, hydrate is not used // hydrate is based on the assumption that the DOM structure is the same for SSR and CSR const container = this.children[0]; container.innerHTML = ''; ReactDOM.render( React.createElement(ShpHeader, props), container); ... ... const container = document.createElement('div’); const props = { hoge: this.getAttribute('hoge') }; const component = React.createElement(ShpHeader, props); ReactDOM.render(component, container); this.appendChild(container); ... CSR Isomorphic Reactコンポーネント描画方式の変更
  57. Effect ⎯ Common UI development cost is 1/8, and reduction

    in workload of about 20 man-months per year (*FY2021 results) Reduction in development cost Reduced lead time ⎯ A change in URL link takes less than an hour Increased number of front deployments ⎯ To use the resources where you want to focus