Slide 1

Slide 1 text

ReactNative + microCMS の設計にすごく悩んだ話 株式会社BeatFit CTO 飯塚 浩也

Slide 2

Slide 2 text

医師 循環器内科、総合診療医と して、⼤学 - 地⽅の病院を 8 年間勤務。 IT は⼤の苦⼿。 パソコン教室のアビバに 通っていた。 エンジニア 株式会社BeatFit にエンジニ アとして⼊社。 [ ⽇課] Codewars, LeetCode Hack The Box Type Challenge

Slide 3

Slide 3 text

今⽇のお話 Headless CMS の技術選定に⾄るまでの経緯 悩んだ設計の話 CMS との差分を埋める React Native ライブラリ

Slide 4

Slide 4 text

みんなの広場

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

弊社運営チームは CMS から投稿したい でも、CMS 周りを コーディング したくない 期限まで あと3 ヶ⽉しかない

Slide 7

Slide 7 text

そうだ microCMS でいこう

Slide 8

Slide 8 text

運⽤⾯ ・⽇本語が魅⼒的だった ・中の⼈が、twitter で だった ・料⾦プランが、優しかった 友達

Slide 9

Slide 9 text

いいね、返信 コメント、通知など 複雑な機能がある React Native での 事例の少なさ よくある HeadlessCMS の Usecase と違う・・・

Slide 10

Slide 10 text

実際に悩んだ設計

Slide 11

Slide 11 text

設計 1. 責務を分離 通常の Feed コンテンツは、CMS ヘ 複雑なwrite 要件のデータは、RDS へ

Slide 12

Slide 12 text

Get request 時に、frontend 側で mapping するロジックが必要になる 😣

Slide 13

Slide 13 text

WebHook を使い、CMS 上 からの投稿や削除が可能。 運営が、不適切な投稿を、CMS でチェックできる。 設計 2. 全データを microCMS で管理

Slide 14

Slide 14 text

データの⼆重管理になり、データ不整合が⼼配。 定期的に同期をする処理が必要になる。 Post request が多く、コストが⾼くなる。 設計 2.

Slide 15

Slide 15 text

twitter でぶつぶつ悩んでたら → microCMS 創業者 ( 柴⽥さん、松⽥さん) からDM

Slide 16

Slide 16 text

神対応、ありがとうございました・・・!😭

Slide 17

Slide 17 text

最終設計: こうなりました!

Slide 18

Slide 18 text

最終設計: Usecase での分離 運営の投稿 User の投稿

Slide 19

Slide 19 text

Appendix Usecase で分離することで、設計が simple になった Post request が少ない設計になり、費⽤⾯で優れた 運営側の投稿のカスタマイズを、細かくできる設計になった 運営側の投稿頻度は少なく、当⾯は Webhook 通信の失敗は 許容できる設計になった

Slide 20

Slide 20 text

microCMS との差分を埋める ライブラリーのご紹介 react-native-rich-editor react-native-render-html

Slide 21

Slide 21 text

Rich Editor in microCMS "textContent": "


あああいいい

アイウエオ

", ↓

Slide 22

Slide 22 text

react-native-rich-editor

Slide 23

Slide 23 text

HTML を取得 const richText = useRef() const html = richText.current?.getContentHtml() (richText.current = r)} placeholder={' ⼊⼒してください'} onChange={handleChange} initialFocus /> 1 2 3 4 5 6 7 8 9 10

Slide 24

Slide 24 text

HTML を取得 const richText = useRef() const html = richText.current?.getContentHtml() (richText.current = r)} placeholder={' ⼊⼒してください'} onChange={handleChange} initialFocus /> 1 2 3 4 5 6 7 8 9 10 const html = richText.current?.getContentHtml() const richText = useRef() 1 2 3 4 (richText.current = r)} 6 placeholder={' ⼊⼒してください'} 7 onChange={handleChange} 8 initialFocus 9 /> 10

Slide 25

Slide 25 text

react-native-render-html import React, { Component } from "react"; import { ScrollView, useWindowDimensions } from "react-native"; import HTML from "react-native-render-html"; const htmlContent = `

This HTML snippet is now rendered with native components !

Enjoy a webview-free and blazing fast application

Look at how happy this native cat is `; export default function Demo() { const contentWidth = useWindowDimensions().width; return ( ); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

Slide 26

Slide 26 text

react-native-render-html import React, { Component } from "react"; import { ScrollView, useWindowDimensions } from "react-native"; import HTML from "react-native-render-html"; const htmlContent = `

This HTML snippet is now rendered with native components !

Enjoy a webview-free and blazing fast application

Look at how happy this native cat is `; export default function Demo() { const contentWidth = useWindowDimensions().width; return ( ); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 const htmlContent = `

This HTML snippet is now rendered with native components !

Enjoy a webview-free and blazing fast application

Look at how happy this native cat is `; import React, { Component } from "react"; 1 import { ScrollView, useWindowDimensions } from "react-native"; 2 import HTML from "react-native-render-html"; 3 4 5 6 7 8 9 10 11 export default function Demo() { 12 const contentWidth = useWindowDimensions().width; 13 return ( 14 15 16 17 ); 18 } 19

Slide 27

Slide 27 text

react-native-render-html import React, { Component } from "react"; import { ScrollView, useWindowDimensions } from "react-native"; import HTML from "react-native-render-html"; const htmlContent = `

This HTML snippet is now rendered with native components !

Enjoy a webview-free and blazing fast application

Look at how happy this native cat is `; export default function Demo() { const contentWidth = useWindowDimensions().width; return ( ); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 const htmlContent = `

This HTML snippet is now rendered with native components !

Enjoy a webview-free and blazing fast application

Look at how happy this native cat is `; import React, { Component } from "react"; 1 import { ScrollView, useWindowDimensions } from "react-native"; 2 import HTML from "react-native-render-html"; 3 4 5 6 7 8 9 10 11 export default function Demo() { 12 const contentWidth = useWindowDimensions().width; 13 return ( 14 15 16 17 ); 18 } 19

Slide 28

Slide 28 text

まとめ 設計に悩んだときは、UseCase で分離すると単⼀責任に なり、設計が simple になる microCMS は、複雑な機能が必要な時も、有効な選択肢 となる react-native-render-html と react-native-rich-editor で 差分を埋められる