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のパフォーマンスを改善する必要がなかった話
Search
teamspirit_minato
May 26, 2017
Technology
2
3.3k
Reactのパフォーマンスを改善する必要がなかった話
現在開発中の自社製品に対し、パフォーマンスを初めて意識した際にまだ特に大きく改善する点が見当たらなかったというだけの話
teamspirit_minato
May 26, 2017
Tweet
Share
Other Decks in Technology
See All in Technology
ワールドカフェI /チューターを改良する / World Café I and Improving the Tutors
ks91
PRO
0
110
〜小さく始めて大きく育てる〜データ分析基盤の開発から活用まで
kniino
0
2.1k
AWS を使う上で知っておきたいオンプレミス知識/aws-on-premise-essentials
emiki
1
4.3k
Java EE/Jakarta EEの現状と将来―クラウドネイティブ時代にJava EEは対応できるのか?―
takakiyo
1
120
MapLibreとAmazon Location Service
dayjournal
1
130
ChatGPT for IT Service Management (IT Pro)
dahatake
7
1.4k
生産性向上チームの紹介
cybozuinsideout
PRO
1
840
KubeCon EU 2024 Recap “Kubernetes Policy Time Machine: Where to Next?”
ryysud
0
180
Kernel MemoryでAzure OpenAI Serviceとお手軽データソース連携
mitsuzono
1
160
反実仮想機械学習とは何か
usaito
PRO
8
2.9k
Discord とビルダー&チャットボットの使い方 / How to use Discord and Builder & Chatbots
ks91
PRO
0
160
推しは推せるときに推せ! プロダクトにフィードバックしていこう
nakasho
0
220
Featured
See All Featured
Fontdeck: Realign not Redesign
paulrobertlloyd
76
4.9k
Designing for humans not robots
tammielis
248
25k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
13
1.5k
How GitHub (no longer) Works
holman
304
140k
Web Components: a chance to create the future
zenorocha
305
41k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
226
51k
Practical Orchestrator
shlominoach
181
9.7k
BBQ
matthewcrist
80
8.8k
A Modern Web Designer's Workflow
chriscoyier
689
190k
Put a Button on it: Removing Barriers to Going Fast.
kastner
58
3k
The Invisible Side of Design
smashingmag
294
49k
Clear Off the Table
cherdarchuk
83
310k
Transcript
ReactͷύϑΥʔϚϯεΛ վળ͢Δඞཁ͕ͳ͔ͬͨ
ࣗݾհɿືɹٛ໌ • ϑϩϯτΤϯυΤϯδχΞ • νʔϜεϐϦοτʹೖࣾ • ήʔϜେ͖ • ࣾͷےτϨڭʹೖ৴ͭͭ͋͠Δ
ຊͷ͓ ωοτͰ࠷ۙReactͷ ύϑΥʔϚϯεΛվળͨ͠Λ Α͘ݟΔͷͰ ࣗͰͬͯΈͨΒ ಛʹඞཁͳ͔ͬͨͱ͍͏
લఏͱͯ͠ ReactͷಛΛৼΓฦΔ
Reactͷ̏ͭͷಛ • JUST THE UI • VIRTUAL DOM • DATA
FLOW VIRTUAL DOMʹΑΓ ඞཁ࠷ݶͷ ύϑΥʔϚϯεकΒΕ͍ͯΔ
͋Γ͕ͱ͏ ͓ΘΓ
͏গ͠ଓ͚·͢ɾɾɾ
·ͱΊ • ReactVirtul DomͰͷࠩߋ৽Λߦ͏ͨΊɹ ࠷ॳ͔Β͋ΔఔͷύϑΥʔϚϯε͕อͯΔ Α͏ʹग़དྷ͍ͯΔɻ
վΊͯ DOM͍ͭߋ৽͞ΕΔͷ͔ʁ
Stateͷߋ৽
container amountΛߋ৽ State͕ߋ৽࣌ɺ࠶ϨϯμϦϯά͕ൃੜ ίϯϙʔωϯτ܈ $PNQPOFOU% $PNQPOFOU& $PNQPOFOU' $PNQPOFOU$ $PNQPOFOU# $PNQPOFOU"
TFU4UBUF \BNPVOUWBMVF^ ࣮ࡍʹBNPVOUΛ͏ ίϯϙʔωϯτ
ٯΛݴ͏ͱɾɾɾ
container setStateʹΑΓ มVΛߋ৽ state͕ίϯϙʔωϯτʹ͍ͬͯΕɺ ྫ͑ະ༻Ͱ࠶ϨϯμϦϯά͕Δ ίϯϙʔωϯτ܈ ίϯϙʔωϯτ $PNQPOFOU% $PNQPOFOU& $PNQPOFOU'
$PNQPOFOU$ $PNQPOFOU# $PNQPOFOU" BNPVOUΛνΣοΫ BNPVOUΛʜ BNPVOUΛ νΣοΫ BN TFU4UBUF \BNPVOUWBMVF^ ࣮ࡍʹBNPVOUΛ͏ ίϯϙʔωϯτ
࠶ϨϯμϦϯάͷ ճΛݮΒ͢ʹʁ
stateઙ͘อͪɺ֤ίϯϙʔωϯτͷ ߋ৽ʹඞཁͳͷ͚ͩ͢Α͏৺͕͚Δ this.state = { // ඞཁͳstateΛҰͭͷΦϒδΣΫτʹશͯ֨ೲ͍ͯ͠Δύλʔϯ masterObject: { date:
‘2017-5-15’, amount: 3000, name: ‘tawashi’, } }; this.state = { // stateΛׂͨ͠ date: ‘2017-5-15’, amount: 3000, name: ‘tawashi’, };
Spread AttributesChildrenͳͲͷ ͝ར༻ܭըతʹ render() { // Spread Attributes return <Meat
{...props} />; } • όέπϦϨʔʹർΕͨਓͷٹੈओ • ͝ར༻ܭըతʹ
ෆཁͳpropsͷड͚͠ΛࢭΊΔ class MeatMarker extends Component { render() { return <Meat
A={this.props.A} B={this.props.B} V={this.props.V} />; } } • ԼҐίϯϙʔωϯτʹ͢ඞཁͳͷͩ ͚ʹ͠·͠ΐ͏ • ϨϏϡʔݟ͔ͬ͠͠Γͱ
ReactϙϦεʢϨϏϡʔΞʣͱͯ͠ ͔ͬ͠Γࣄ͍͖ͯ͠·͠ΐ͏
·ͱΊ • ReactVirtul DomͰͷࠩߋ৽Λߦ͏ͨΊɹ ɹ ࠷ॳ͔Β͋ΔఔͷύϑΥʔϚϯε͕อͯΔ Α͏ʹग़དྷ͍ͯΔɻ • React͕ύϑΥʔϚϯεΛൃشͰ͖ΔΑ͏ʹߏ ͞Ε͍ͯΔ͔ৗʹ֬ೝ͢Δɻ
͏ҰؤுͬͯΈΔ
componentWillUpdate(nextProps) { console.log(this.state.amount); console.log(nextProps.amount); } // લճͱඳը݁Ռ͕Ұॹ͕ͩ࠶ϨϯμϦϯά࣮ࢪ͞ΕΔ render(){ ɹˡɹ return
(<p>{amount}</p>); } ߋ৽ͷલޙͰState͕ಉҰͷ߹Ͱ ࠶ϨϯμϦϯά͕Δ
࠶ϨϯμϦϯάͷ ճΛݮΒ͢ʹʁ
shouldComponentUpdate
shouldComponentUpdate class MeatMarker extends Component { shouldComponentUpdate: function(nextProps, nextState) {
if (this.props.userName !== nextProps.userName) { return true;ɹˡ update࣮ࢪ } else { return false;ɹˡɹupdate͞Εͳ͍ } } • ίϯϙʔωϯτΛ࠶ඳը͢Δ͔Ͳ͏͔Λܾఆ͢Δ • updateલʹ࣮ߦ͞ΕΔɻ • ΓͰfalseΛฦͤupdate࣮ࢪ͞Εͳ͍ɹ (σϑΥϧτͰඞͣtrue͕ฦΓ·͢)
shouldComponentUpdateΑ͋͘Δ࣮ shouldComponentUpdate: function(nextProps, nextState) { // user໊͕ߋ৽લޙͰಉҰͳΒߋ৽ॲཧ࣮ࢪ͠ͳ͍ return this.props.userName !==
nextProps.userName; } ̍.݅Λઃܭ࣮ͯ͠ 2.lodashimmutable.jsΛར༻࣮ͨ͠ shouldComponentUpdate: function(nextProps, nextState) { // ߋ৽લޙͰ͕มΘ͍ͬͯͳ͚Εɺupdate࣮ࢪ͠ͳ͍ const propsDiff = _.isEqual(nextProps, this.props); const stateDiff = _.isEqual(nextState, this.state); return !(propsDiff && stateDiff); }
PureComponentͰOK class MeatMarker extends Component { constructor(props) { super(props); ɹɹɹɹɹɹɹ!
//extendsઌΛPureComponentʹมߋ͢Δʮ͚ͩʯͰར༻Ͱ͖Δ class MeatMarker extends PureComponent { constructor(props) { super(props); • React v15.3Ҏ߱Ͱ࣮͞Ε͍ͯΔ • shouldComponentUpdateΛཪͰ࣮ • શͯͷstateͱpropsʹshallowͳൺֱΛ࣮ࢪ
೦ͷͨΊͷshallowͳൺֱͷ͓͞Β͍ ̍ճ api.get("/api/user",(req, res) => { this.setState({user:res}) ); console.log(this.state.user); ݁Ռ
{user: ‘minato’ , company: ‘TeamSpirit’} ̎ճ api.get("/api/user",(req, res) => { this.setState({user:res}) ); console.log(this.state.user); ݁Ռ {user: ‘minato’ , company: ‘TeamSpirit’} ̍ճͱ̎ճͰผͷΦϒδΣΫτΛ ੜ͍ͯ͠ΔͷͰtrue͕ؼΓ·͢
WARNING!
Կߟ࣮͑ͣ͢Δͷ·͍ͣ class BaseComponent extends React.Component { shouldComponentUpdate: function(nextProps, nextState) {
const propsDiff = _.isEqual(nextProps, this.props); const stateDiff = _.isEqual(nextState, this.state); return !(propsDiff && stateDiff); } } ɹྫ͑ҎԼͷΑ͏ʹߋ৽લޙͷstateɺprops Λൺֱ͢ΔBaseClassΛ࣮͠ɺશͯͷclassͰܧ ঝͯ͠ൺֱॲཧΛ࣮͢ΔͱɺٯʹύϑΥʔϚ ϯε͕Լ͢ΔՄೳੑ͕͋Δʢͱݴ͏͔͢Δʣ
Ͳ͜ʹ࣮͖͔͢ ͪΌΜͱݕ౼͔ͯ͠Βʹ ͠·͠ΐ͏
·ͱΊ • ReactVirtul DomͰͷࠩߋ৽Λߦ͏ͨΊɹ ɹ ࠷ॳ͔Β͋ΔఔͷύϑΥʔϚϯε͕อͯΔ Α͏ʹग़དྷ͍ͯΔɻ • React͕ύϑΥʔϚϯεΛൃشͰ͖ΔΑ͏ʹߏ ͞Ε͍ͯΔ͔ৗʹ֬ೝ͢Δɻ
• shouldComponentUpdateͰߋ৽લޙͷ͕ ಉҰͷ߹ʹߋ৽ॲཧΛߦΘͳ͍Α͏ʹ͢Δ
͜͜·Ͱ༧
͔͜͜Βରྍ๏
ύϑΥʔϚϯεͷ ϘτϧωοΫΛ୳͢
PerfͷಋೖɻPerfͱԿ͔ʁ • ίϯϙʔωϯτͷඳըʹ͔͔Δ࣌ؒΛௐΔ ͜ͱ͕Ͱ͖Δπʔϧ • ϒϥβͷίϯιʔϧ্Ͱಈ࡞͢Δ ↓͜Μͳײ͡ͷ݁Ռ͕ग़ͯͲ͜ʹ͕͔͔͍࣌ؒͬͯΔ֬ೝͰ͖Δ
PerfͰͷݪҼಛఆͱରॲํ๏ import React from ‘react'; import Perf from 'react-addons-perf'; class
MeatMaker extends React.Component { componentDidMount() { window.Perf = Perf; }; } 1. componentDidMountͰPerfΛWindowʹ ηοτ͢Δɻ Reactιʔείʔυ
PerfͰͷݪҼಛఆͱରॲํ๏ 2. Perf.start()Λ࣮ߦɻ 3. ͖ͳ͚ͩΞΫγϣϯΛى͜͢ɻ 4. Perf.stop()Λ࣮ߦɻ 5. getLastMeasurementsͰ༰Λ֬ೝ͠ɺ࣌ؒ ͕͔͔͍ͬͯΔՕॴΛ֬ೝɻ
ϒϥβίϯιʔϧ ͜͜ΒลͳΜ͔ͦ͏
PerfͰͷݪҼಛఆͱରॲํ๏ʢผղʣ import React from ‘react'; import Perf from 'react-addons-perf'; class
MeatMaker extends React.Component { componentDidMount() { window.Perf = Perf; } render (){ return ( <div> {Perf.start()} <MeatMaker /> {Perf.stop()} <ChikenMaker /> </div> ); } } ίϯϙʔωϯτͷಡΈࠐΈલޙͰstartɺstopΛ࣮ ࢪɺ֬ೝͦͷޙϒϥβ͔ΒߦͬͯOK
ݪҼॴΛಛఆͨ͠ޙͷରॲํ๏ʁ جຊલ߲·ͰͷLTͷ༰Λ ࢥ͍ฦ͍͚ͯͨͩ͠Ε େৎʢͷͣʣʂ
۩ମతʹʁʢ͓͞Β͍ʣ • ߏΛݟ͠ • ෆཁͳpropsͷআ • shouldComponentUpdate(PureComponent) ͷ࣮
ݪҼͱରॲฤʢ͓·͚ʣ getSubContainer() { switch (this.state.selectedKey) { case 'meat': return (<Meat
/>); case 'chicken': return (<chicken />); default : return null; } }Window.Perf.start()Λ࣮ߦ ↓ຖճίϯϙʔωϯτΛ࠶࡞͍ͯ͠ΔͷͰॏ͍
ݪҼͱରॲฤʢ͓·͚ʣ renderSubContainer() { {const meat = this.state.selectedKey === ‘meat’ }
{const chicken = this.state.selectedKey === ‘chicken’ } return ( <div> <Meat visible={meat} /> <Chicken visible={chicken} />); </div> ); } ঢ়گʹԠͯ͡ίϯϙʔωϯτΛඇදࣔʹ͠ɺ ࠶࡞ࣙΊͯΈͨ
࠶ϨϯμϦϯάૣ͘ͳͬͨʂ
͕
ॳظදࣔ͘ͳΓ ϝϞϦͷৗ࣌ͷ༻ྔ૿͑ͨ
ଥͳτϨʔυΦϑ͔ ݕূඞཁ ΫϫΨλ खฤΈͷϚϑϥʔ
·ͱΊ • ReactVirtul DomͰͷࠩߋ৽Λߦ͏ͨΊɺ࠷ॳ͔Β ͋ΔఔͷύϑΥʔϚϯε͕อͯΔΑ͏ʹग़དྷ͍ͯΔɻ • React͕ύϑΥʔϚϯεΛൃشͰ͖ΔΑ͏ʹߏ͞Εͯ ͍Δ͔ৗʹ֬ೝ͢Δɻ • shouldComponentUpdateͰߋ৽લޙͷ͕ಉҰͷ߹
ʹߋ৽ॲཧΛߦΘͳ͍Α͏ʹ͢Δɻ • ϨϯμϦϯά͕͍߹PerfΛͬͯݪҼΛಛఆ͠ɺ ରॲྍ๏Λ࣮͢Δɻ࣮ܭըతʹ
࠷ޙʹࠓߋͰ͕͢ λΠτϧͷ݅ʹ͍ͭͯ
ॳΊͯฐࣾͷͷύϑΥʔϚϯεΛҙࣝͨ࣌͠ • ฐࣾͷϓϩμΫτࠒͷϨϏϡʔΛ͋Δఔ ͔ͬ͠Γ͍ͬͯͨ͜ͱ͋Γɺɹɹɹɹ ผʹࠓ͙͢ύϑΥʔϚϯεΛҙࣝͨ͠मਖ਼Λ ࣮ࢪ͠ͳ͍͍͔ͯ͘ͳɻͱ͍͏ͷ͕࠷ॳͷ ײͰͨ͠ɻ • ࣮ͯ͠ମײͰ͖Δఔͷ͕ࠩ͋·Γແ͘ɺ ଞͷݕ౼ࣄ߲͕ग़ͦ͏ͩͬͨ
• ϚδͰࠔͬͨΒPerfͰͳΜͱ͔͢Δ
·ͱΊͷ·ͱΊ • ReactVirtual Domͷࢥ͋Γɺҙࣝͤͣ ͱύϑΥʔϚϯε͋Δఔग़Δɻ • ઃܭͱࠒͷϨϏϡʔ͕େࣄɻઃܭࠒͷ ϨϏϡʔ͕ສશͳΒɺͦͦύϑΥʔϚ ϯεͷվળࣗମ͕ෆཁͳ͜ͱଟ͍ɻ •
ϚδͰࠔͬͨΒPerfͰͳΜͱ͔͢Δ
ྑ͍ReactϥΠϑΛ
͝੩ௌ ͋Γ͕ͱ͏͍͟͝·ͨ͠