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
React v16 and beyond React Fiber
Search
koba04
September 24, 2017
Programming
9.6k
11
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
React v16 and beyond React Fiber
HTML5 Conference 2016
http://events.html5j.org/conference/2017/9/session/#a4
koba04
September 24, 2017
More Decks by koba04
See All by koba04
フロントエンドの現在地とこれから
koba04
10
5.4k
Standing on the shoulders of giants
koba04
0
3.2k
React/Next によるアプリケーション開発のこれから
koba04
61
19k
フロントエンド刷新をプロジェクトとして進める際に気をつけていること
koba04
3
2k
How useEvent would change our applications
koba04
1
3.3k
kintoneフロントエンド刷新によるモノリスからの脱却とその先に目指す未来
koba04
3
16k
Make it Declarative with React
koba04
0
2k
Ready for React in 2019
koba04
2
1.8k
Algorithms in React
koba04
14
19k
Other Decks in Programming
See All in Programming
そこに3びきプロダクトがいるじゃろう——生成AI時代における“価値が届かない理由”の構造
kosuket
0
470
php-fpmのプロセスが枯渇した日-調査・対処・そして本当にやるべきだったこと-
shibuchaaaan
0
280
GDG Korea Android: 2026 I/O Extended ~ What's new in Android development tools
pluu
0
220
ここ半年くらいでAIに作らせたR用ツール
eitsupi
0
380
ITヒヤリハットを整理してみた ~ライフサイクルと原因から考える再発防止策~
koukimiura
1
140
yield再入門 #phpcon
o0h
PRO
0
1k
Go 1.27 における memory allocation の高速化
andpad
0
170
為什麼你並不需要ViewModel / No, you don't need a ViewModel
lovee
1
490
改善しないと、タスクが回らない。 “てんこ盛りポジション” を引き継いだ情シスの、入社3ヶ月の業務改善録
krm963
0
260
Apache Hive: そしてCloud Native Lakehouseへ
okumin
1
220
実装をデザインガイドラインに追従させるための取り組み / 260731-dip-mosh-design-system
dachi023
0
440
freee が目指す データ マネジメント戦略 AI-Ready 時代を支える 攻めのガバナンスとは
freee
PRO
0
360
Featured
See All Featured
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
630
Abbi's Birthday
coloredviolet
3
9.3k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
Paper Plane
katiecoart
PRO
2
53k
The Curious Case for Waylosing
cassininazir
1
450
The Language of Interfaces
destraynor
162
27k
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
200
The Spectacular Lies of Maps
axbom
PRO
1
910
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
390
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
1
260
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.9k
Transcript
3FBDUWBOECFZPOE3FBDU'JCFS )5.-$POGFSFODF !LPCB
!LPCB
!LPCB
w 3FBDUWͰͷมߋ w 3FBDU'JCFS w 8IBU w 8IZ
w )PX "HFOEB
3FBDUW
w ͿΓͷϝδϟʔόʔδϣϯΞοϓ w WͷϦϦʔεɺ w ޓੑΛอͪͳ͕Βͷ෦࣮ͷॻ͖͑ˠ3FBDU'JCFS w WΛ͍ͬͯΕεϜʔζʹΞοϓσʔτͰ͖Δʢͣʣ w XBSOJOHCSFBLJOHDIBOHFͷྲྀΕ
w ͨͩ͠ɺ%0.ͷѻ͍ϥΠϑαΠΫϧΠϕϯτͷॱ൪ͳͲͰϋ ϚΔ߹͋Δ͔ w ϥΠηϯε͕#4% 1BUFOT͔Β.*5ʹ/FX 3FBDUW
w #4% 1BUFOT͔Β.*5ʹ -JDFOTF IUUQTDPEFGBDFCPPLDPNQPTUTSFMJDFOTJOHSFBDUKFTUqPXBOEJNNVUBCMFKT
/FX'FBUVSFTJOW
3FOEFSTUSJOHBOEBSSBZ
w SFOEFS͔ؔΒจࣈྻྻΛฦ͢͜ͱ͕Ͱ͖ΔΑ͏ʹ 3FOEFSTUSJOHBOEBSSBZ // จࣈྻ const DisplayName = ({user}) =>
`${user.name} (@${user.id})`; <DisplayName user={{name: ‘Toru Kobayashi’, id: ‘koba04’}} /> // Toru Kobayashi (@koba04) // ྻ const Row = ({children}) => <tr>{children}</tr>; const Columns = ({items}) => ( items((item, i) => <td key={i}>{item}</td> ); <Row> <Columns items={[‘foo’, ‘bar’, ‘baz’]} /> </Row>
w +49ͰγϯλοΫεͱͯ͠αϙʔτ͢Δͱ͍͏ٞ w 4VQQPSUTUBOEBMPOFGSBHNFOUTZOUBY w IUUQTHJUIVCDPNGBDFCPPLKTYJTTVFT 3FOEFSTUSJOHBOEBSSBZ [ <Child key={1}
/>, <Child key={2} />, <Child key={3} /> ] !!! <> <Child /> <Child /> <Child /> </>
&SSPS#PVOEBSJFT
w USZDBUDIͷ༷ʹɺࢠ$PNQPOFOUͷSFOEFSϥΠϑαΠΫϧϝ ιουͰى͖ͨΤϥʔΛΩϟον͢ΔͨΊͷϥΠϑαΠΫϧϝ ιου͕Ճ w ˠDPNQPOFOU%JE$BUDI w W͔ΒࢠSFOEFSϥΠϑαΠΫϧϝιουͰى͖ͨΤϥʔͷ ѻ͍͕มΘΔ &SSPS#PVOEBSJFT
w W·ͰɺSFOEFSϥΠϑαΠΫϧϝιουͰΤϥʔ͕ى͖ ͯ$PNQPOFOUͦͷ·· w ˠෆ߹ͳ7JFXΛϢʔβʔʹදࣔͯ͠͠·͏Մೳੑ w WͰɺΤϥʔ͕ൃੜͨ͠Β3FBDU%0.SFOEFSͰࢦఆͨ͠ SPPUDPOUBJOFS͔ΒΞϯϚϯτ͢Δ w ˠΞϯϚϯτ͞Εͨ͘ͳ͍߹ΤϥʔΛϋϯυϦϯά͢
Δඞཁ͕͋Δ &SSPS#PVOEBSJFT
&SSPS#PVOEBSJFT class Child extends React.Component { componentDidMount() { throw new
Error(‘Something went wrong!!’); } } class App extends React.Component { constructor(props) { super(props); this.state = { error: null }; } componentDidCatch(error, info) { // info.componentStackComponentͷStackTraceจࣈྻ this.setState(() => ({error})); } render() { return this.state.error ? <p>Τϥʔ͕ൃੜ͠·ͨ͠</p> : <Child />; } }
1PSUBM
w 3FBDU%0.DSFBUF1PSUBM w ҙͷ%0.ʹର͢ΔSFOEFSΛ$PNQPOFOUπϦʔͷҰ෦ͱ͠ ͯѻ͏͜ͱ͕Ͱ͖Δ w ϥΠϑαΠΫϧϝιουͳͲ௨ৗͷࢠ$PNQPOFOUͱಉ༷ʹ ѻΘΕΔ 1PSUBM
w 1PSUBMΛΘͳ͍ྫ 1PSUBM class App extends React.Component { componentDidUpdate() {
const container = document.querySelector(‘.modal-container’); if (this.state.modal) { ReactDOM.render( <Modal type={this.state.modal} onClose={() => { this.setState( () => ({modal: null}), () => ReactDOM.unmountComponentAtNode(container) ); }} />, container ); } } }
w 1PSUBMΛͬͨ߹ 1PSUBM class App extends React.Component { render() {
return ( <section> <Contents /> {this.state.modal && ReactDOM.createPortal( <Modal type={this.state.modal} onClose={() => { this.setState(() => ({modal: null})); } />, document.querySelector(‘.modal-container’) )} </section> ); } }
'MBU#VOEMFT
w #SPXTFSJGZΛͬͨϏϧυ͔Β3PMMVQΛͬͨϏϧυʹ w ̍ͭͷϞδϡʔϧͱͯ͠Ϗϧυ͢Δ͜ͱͰɺϑΝΠϧαΠζͷ ݮɺύʔεʹ͔͔Δ࣌ؒΛݮ w ͜ͷ݁ՌɺASFBDUMJCYYYAͷΑ͏ͳ෦Ϟδϡʔϧͷࢀ রʢ%JSFDU*NQPSUʣ͕ෆՄೳʹ w ґଘ͍ͯ͠ΔSEQBSUZMJCSBSZରԠ͕ඞཁ
w SFBDUUBQFWFOUQMVHJO SFBDUOBUJWFXFCʜ 'MBU#VOEMFT
'MBU#VOEMFT node_modules/react "## cjs $ "## react.development.js $ %## react.production.min.js
"## index.js node_modules/react-dom "## cjs $ "## react-dom-server.browser.development.js $ "## react-dom-server.browser.production.min.js $ "## react-dom-server.node.development.js $ "## react-dom-server.node.production.min.js $ "## react-dom-test-utils.development.js $ "## react-dom-unstable-native-dependencies.development.js $ "## react-dom-unstable-native-dependencies.production.min.js $ "## react-dom.development.js $ %## react-dom.production.min.js "## index.js
4FSWFS4JEF3FOEFSJOH
w શʹಠཱͨ͠3FOEFSFSʹʢطଘ࣮͕ϕʔεʣ w 3FBDU1BSUJBM3FOEFSFSKTͱ͍͏ϑΝΠϧ - ʹ w 4USFBN3FOEFSJOHͷαϙʔτ w )ZESBUJPO4USBUFHZͷมߋ
w )ZESBUJPOʜ443ͨ͠)5.-ΛΫϥΠΞϯτͰͷϨϯμϦ ϯά࣌ʹ࠶ར༻͢Δ w 3FBDU%0.IZESBUF ͷՃ 4FSWFS4JEF3FOEFSJOH
w SFOEFS5P/PEF4USFBN SFOEFS5P4UBUJD/PEF4USFBNͷՃ 4USFBN3FOEFSJOH import ReactDOMServer from ‘react-dom/server’; const App
= () => ( <div> <p>Hello Stream!</p> </div> ); ReactDOMServer.renderToNodeStream(<App />).pipe(process.stdin); // <div data-reactroot=""><p>Hello Stream!</p></div> ReactDOMServer.renderToStaticNodeStream(<App />).pipe(process.stdin); // <div><p>Hello Stream!</p></div>
w 3FBDU%0.IZESBUF ͱ͍͏໌ࣔతͳ"1*ͷՃ w WͰɺ3FBDU%0.SFOEFS ʹΑΔ)ZESBUFҾ͖ଓ͖ αϙʔτʢAEBUBSFBDUSPPUAଐੑʹΑͬͯఆʣ w 3FBDU&MFNFOUͷ୯ҐͰՄೳͳݶΓ࠶ར༻͞ΕΔΑ͏ʹ w
W·Ͱɺ%0.ߏ͕શʹҰக͢Δ͔Ͳ͏͔ΛνΣο ΫαϜʹΑͬͯఆ w /PNPSFAEBUBSFBDUDIFDLTVNABOEAEBUBSFBDUJEA )ZESBUJPO4USBUFHZ
%0."UUSJCVUFT
w ϗϫΠτϦετʹͳ͍ଐੑ%0.ʹө͞ΕΔΑ͏ʹ w WͰɺXBSOJOHTUSJQ w ADMBTTAAGPSAAPOʙAͳͲআ͘ w ෆਖ਼ͳܕͷଐੑTUSJQ͞ΕΔΑ͏ʹ w WͰɺจࣈྻԽͯ͠ద༻͞Ε͍ͯͨ
%0."UUSJCVUFT <div someExperimentalAttribute=“foo” /> <div className={false} /> // v16 <div /> & warning // v15 <div className=“false” /> .PSFIUUQTGBDFCPPLHJUIVCJPSFBDUCMPHEPNBUUSJCVUFTJOSFBDUIUNM
1PMZpMM
w .BQ 4FU SFRVFTU"OJNBUJPO'SBNF͕ඞཁʹ w αϙʔτ͢ΔϒϥβʔʹԠͯ͡1PMZpMMΛೖΕΔ 1PMZpMM import ‘core-js/es6/map’; import
‘core-js/es6/set’; import raf from ‘raf’; if (!window.requestAnimationFrame) { window.requestAnimationFrame = raf; }
0UIFS$IBOHFT
w 3FBDUDSFBUF$MBTT 3FBDU1SPQ5ZQFTͷআ w "EEPOϏϧυͷআ w ͍͔ͭ͘ͷέʔεͰɺߋ৽࣌ͷ"1*ݺͼग़͠ॱ͕มߋʹ w TFU4UBUFͷίʔϧόοΫɺϥΠϑαΠΫϧϝιουɺ3FG w
IUUQTHJUIVCDPNGBDFCPPLSFBDUCMPCNBTUFS $)"/(&-0(NE <6OSFMFBTFE>TFDUJPO 0UIFS$IBOHFT
8IFO
.BZCFOFYUXFFL
3FBDU'JCFS
w 3FBDUͷίΞΞϧΰϦζϜͷ࠶࣮ w ࠷ॳͷ13 w طଘͷ࣮ͱޓੑΛอͪͳ͕ΒɺॊೈͳεέδϡʔϦϯάΛ Մೳʹ w WͰɺޓੑͷ͋Δঢ়ଶͰϦϦʔε͞ΕͯɺPQUJOͰඇಉ ظ3FOEFSJOH͕Մೳʹ
w ඇಉظ3FOEFSJOHपΓ࣮த 3FBDU'JCFSͱ
طଘ࣮ͷ
w ߋ৽ॲཧ͕શͯಉظతɻπϦʔશମͷࠩͷݕग़ʙ%0.ͷ өɺϥΠϑαΠΫϧϝιουͷݺͼग़͕͠શͯಉظͰ࣮ߦ͞ ΕΔ طଘ࣮ͷ <App /> <div /> <Button
/> <List /> <Item /> <Item /> <Item /> ࠶ؼత & ಉظత ↓ UIΛϒϩοΫ͢Δ & ϑϨʔϜམͪ mount mount mount
طଘ࣮ͷ Key Input API Response Ωʔೖྗ͕ ϒϩοΫ αʔόʔ͔Βͷ ϨεϙϯεΛॲཧ Key
Input Key Input Key Input Key Input
3FBDU'JCFSʹΑΔղܾํ๏
w ߋ৽ॲཧΛεέδϡʔϦϯάՄೳʹ w ߋ৽ॲཧʹର͢Δ༏ઌ͚ w $PNQPOFOUʹର͢Δ༏ઌ͚ 3FBDU'JCFSʹΑΔղܾํ๏ ୯७ͳॲཧͷߴԽͰͳ͘ɺ 6*ͷϨεϙϯεੑΛ্ͤ͞Δ͜ͱ͕త
3FBDU'JCFSʹΑΔղܾํ๏ Key Input ߋ৽Λ Chunkʹ ղͯ͠ద༻ Key Input Key Input
Key Input API Response ༏ઌߴ ༏ઌ
3FBDU"SDIJUFDUVSF
3FBDU"SDIJUFDUVSF <div /> Component + JSX Reconciler Renderer <App />
<Text /> Fiber Stack DOM Native View Canvas
w 3FBDU&MFNFOUͷπϦʔΛߏங͢Δ w $PNQPOFOUΛϚϯτɺߋ৽ɺΞϯϚϯτ͢Δ w ϥΠϑαΠΫϧϝιουΛݺͼग़͢ w ࠩΛܭࢉ͢Δ w 3FOEFSFSʹࠩΛ͑Δ
w ॴҦɺ7JSUVBM%0.ͱݴΘΕ͍ͯͨ෦ 3FDPODJMFS
4DIFEVMJOH
w ࣌ؒϕʔεͷεέδϡʔϦϯά w SFRVFTU*EMF$BMMCBDLΛͬͨεέδϡʔϦϯά w ༏ઌϕʔεͷεέδϡʔϦϯά w ߴ༏ઌͷߋ৽ɺ༏ઌͷߋ৽ʹׂΓࠐΉ͜ͱ͕Ͱ͖Δ w ׂΓࠐ·Εͨߋ৽ॲཧޙ͔Β࠶։Ͱ͖Δ
w ݱ࣌Ͱ༏ઌͱͯ͠ɺl4ZODz l5BTLz l)JHIz l-PXz l0⒎4DSFFOz͕ఆٛ͞Ε͍ͯΔ 4DIFEVMJOH
SFRVFTU*EMF$BMMCBDL const work = (deadline) => { if (deadline.timeRemaining() >
10) { // do some heavy tasks } else { requestIdleCallback(work); } }; requestIdleCallback(work); Fig. 1 Example of an inter-frame idle period (https://www.w3.org/TR/requestidlecallback/)
'JCFSͷσʔλߏ
'JCFSͷσʔλߏ export type Fiber = {| tag: TypeOfWork, key: null
| string, type: any, stateNode: any, return: Fiber | null, child: Fiber | null, sibling: Fiber | null, index: number, ref: null | (((handle: mixed) => void) & {_stringRef: ?string}), pendingProps: any, memoizedProps: any, updateQueue: UpdateQueue | null, memoizedState: any, internalContextTag: TypeOfInternalContext, effectTag: TypeOfSideEffect, nextEffect: Fiber | null, firstEffect: Fiber | null, lastEffect: Fiber | null, pendingWorkPriority: PriorityLevel, alternate: Fiber | null, _debugID?: DebugID, _debugSource?: Source | null, _debugOwner?: Fiber | ReactInstance | null, _debugIsCurrentlyTiming?: boolean, |};
-JOLFE-JTUߏ let root = fiber; let node = fiber; while
(true) { // Do something with node if (node.child) { node = node.child; continue; } if (node === root) { return; } while (!node.sibling) { if (!node.return || node.return === root) { return; } node = node.return; } node = node.sibling; } From: Fiber Principles: Contributing To Fiber #7942 https://github.com/facebook/react/issues/7942
Text = () => '...'; List = () => [
<div>...</div>, <div>...</div>, ]; class App extends React.Component { render() { return ( <main> <h2>...</h2> <div> <Text /> <List /> </div> </main> ); } } ReactDOM.render(<App />, container) HostRoot <App /> <main /> <h2 /> <div /> <Text /> HostText List <div /> <div /> 1 2 3 4 5 6 8 9 10 7 Ͳ͔͜ΒͰதஅʙ࠶։ Ͱ͖Δ
1IBTFT
w 3FBDU'JCFSl#FHJOz l$PNQMFUFz l$PNNJUzͷϑΣʔζΛ࣋ͬͯ ͍Δ w #FHJOʙ$PNQMFUF w 'JCFS $PNQPOFOU
ͷ୯ҐͰॲཧ͞ΕΔ w Πϯελϯεͷ࡞ɺSFOEFSؔͷ࣮ߦ ࠩܭࢉ w $PNNJU w ߋ৽ॲཧͷ୯ҐͰॲཧ͞ΕΔ w ෭࡞༻Λ·ͱΊͯө͢Δ %0.ͷߋ৽ͳͲ 1IBTFT
w #FHJOϑΣʔζ w DPNQPOFOU8JMM.PVOU DPNQPOFOU8JMM3FDFJWF1SPQT TIPVME$PNQPOFOU6QEBUF DPNQPOFOU8JMM6QEBUF w ඇಉظ3FOEFSJOHͰɺதஅʙ࠶։͞ΕΔ͜ͱͰෳճݺ
ΕΔ͜ͱ w $PNNJUϑΣʔζ w DPNQPOFOU%JE.PVOU DPNQPOFOU%JE6QEBUF DPNQPOFOU8JMM6ONPVOU ϥΠϑαΠΫϧϝιου
෭࡞༻·ͱΊͯҰͰө͞ΕΔ FiberA FiberB FiberD FiberE Commit all SideEffects Idle Time
Idle Time Idle Time Beginʙ Complete SideEffect SideEffect SideEffect Host (DOM) FiberC
1SJPSJUZ
)JHI1SJPSJUZͷߋ৽ॲཧׂΓࠐΈͰ͖Δ FiberA FiberB FiberA FiberC Commit Low Priority High Priority
Commit FiberA FiberB FiberC Low Priority ࠶ར༻ ׂΓࠐΈʂ தஅ
σϞ https://koba04.github.io/react-fiber-resources/examples/
4UBDLSFDPODJMFS
4ZOD1SJPSJUZʹΑΔߋ৽
-PX1SJPSJUZʹΑΔߋ৽ॲཧ BeginʙComplete Commit
0⒎4DSFFO1SJPSJUZ TabA TabB hidden hidden Viewport hidden
w %0.3FOEFSFSͷ߹ɺIJEEFO1SPQΛ͏ 0⒎4DSFFO1SJPSJUZ App = () => ( <div> <ul
hidden> <li>xxx</li> : 1000items <li>xxx</li> </ul> <ul> <li>xxx</li> : 1000items <li>xxx</li> </ul> </div> ); ReactDOM.render(<App />, container);
w %0.3FOEFSFSͷ߹ɺIJEEFO1SPQΛ͏ 0⒎4DSFFO1SJPSJUZ App = () => ( <div> <ul
hidden> <li>xxx</li> : 1000items <li>xxx</li> </ul> <ul> <li>xxx</li> : 1000items <li>xxx</li> </ul> </div> ); ReactDOM.render(<App />, container); ݱ࣌ͰɺFeatureϑϥάʹΑͬͯӅ͞Ε͍ͯΔ
ඇಉظ3FOEFSJOHΛࢼ͢
w 3FBDU%0.VOTUBCMF@EFGFSSFE6QEBUFTΛͬͨ-PX 1SJPSJUZʹΑΔߋ৽ w 3FBDUVOTUBCMF@"TZOD$PNQPOFOUΛͬͯߋ৽Λ-PX 1SJPSJUZʹ w 3FBDU%0.'FBUVSF'MBHTpCFS"TZOD4DIFEVMJOHΛ༗ޮʹ͠ ͯσϑΥϧτΛ-PX1SJPSJUZʹ w
0⒎4DSFFO1SJPSJUZར༻Մೳʹ w 3FBDU%0.qVTI4ZOD ඇಉظ3FOEFSJOHΛࢼ͢
ඇಉظ3FOEFSJOHΛࢼ͢ // Low PriorityʹΑΔߋ৽ ReactDOM.unstable_deferredUpdates(() => { this.setState(updater); }); //
ߋ৽͕Low Priorityͱͯ͠ѻΘΕΔComponent const AsyncComponent = React.unstable_AsyncComponent; <AsyncComponent> <App /> </AsyncComponent> // or class App extends AsyncComponent { onClick() { // Sync Priority ReactDOM.flushSync(() => this.setState(() => newState)); } }
ඇಉظ3FOEFSJOHΛࢼ͢ // Low PriorityʹΑΔߋ৽ ReactDOM.unstable_deferredUpdates(() => { this.setState(updater); }); //
ߋ৽͕Low Priorityͱͯ͠ѻΘΕΔComponent const AsyncComponent = React.unstable_AsyncComponent; <AsyncComponent> <App /> </AsyncComponent> // or class App extends AsyncComponent { onClick() { // Sync Priority ReactDOM.flushSync(() => this.setState(() => newState)); } } v17Ҏ߱ͰͷAPIݱ࣌Ͱະఆ
$VTUPN3FOEFSFS
w $VTUPN3FOEFSFSΛ࣮͢ΔͨΊͷํ๏͕ఏڙ͞ΕΔ w ASFBDUSFDPODJMFSA w 3FBDUSFDPODJMFSQBDLBHF w IUUQTHJUIVCDPNGBDFCPPLSFBDUQVMM w
'MPXUZQFʹΑͬͯΠϯλʔϑΣΠε͕ఆٛ͞Ε͍ͯΔ w IUUQTHJUIVCDPNGBDFCPPLSFBDUCMPCNBTUFSTSD SFOEFSFSTTIBSFEpCFS3FBDU'JCFS3FDPODJMFSKT $VTUPN3FOEFSFS
$VTUPN3FOEFSFS $POTPMF ReactConsole.render( <div> <red>Hello</red> <yellow>World</yellow> <cyan>React</cyan> <rainbow>Custom Renderer!</rainbow> </div>,
() => console.log( colors.inverse('##### Update ######’) ) ); ReactConsole.render( <div> <green>Hello</green> <yellow>World2</yellow> <cyan>React</cyan> </div> ); IUUQTHJTUHJUIVCDPNLPCBDCECEGBFDB
$VTUPN3FOEFSFS 7PJDF ReactVoice.render([ <alex key={1}>Hello</alex>, <victoria key={2}>React Fiber</victoria>, <kyoko key={3}>͜Μʹͪ
HTML5 Conference</kyoko>, ]); ??? IUUQTHJTUHJUIVCDPNLPCBFBGDBFBDEFGE
ಠࣗʹ3FBDU%0.-JUFΛ࣮Ͱ͖Δʂ
'VUVSF
w WͰɺඇಉظ3FOEFSJOH -PX1SJPSJUZ ͕σϑΥϧτʹ w %ZOBNJDJNQPSUΛ1SPNJTF$PNQPOFOUͱͯ͠αϙʔτʁ w 3FBTPO3FBDU͔Βͷ1PSU 3FEVDFSFUD
w কདྷతʹ3FBDU'JCFSΛผݴޠͰ࣮͢ΔՄೳੑʁ 'VUVSF
'VUVSF React Fiber (written by C or C++ or…) Native
module for ReactNative Web Assembly for ReactDOM
·ͱΊ
w W3FBDU'JCFS͕ΘΕΔॳΊͯͷόʔδϣϯ w Wͷ࣌Ͱɺ3FBDU'JCFSʹΑͬͯܶతʹߴԽ͞ΕΔ͜ͱ ͳ͍ɻࠓޙͷͨΊͷΠϯϑϥ w 3FBDU'JCFSɺ6*ͷϨεϙϯεੑΛεέδϡʔϦϯάʹΑͬ ্ͯͤ͞Δ ·ͱΊ
5IBOLT TQFBLFSEFDLDPNLPCB