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
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
teamspirit_minato
May 26, 2017
Technology
2
3.6k
Reactのパフォーマンスを改善する必要がなかった話
現在開発中の自社製品に対し、パフォーマンスを初めて意識した際にまだ特に大きく改善する点が見当たらなかったというだけの話
teamspirit_minato
May 26, 2017
Tweet
Share
Other Decks in Technology
See All in Technology
AIと新時代を切り拓く。これからのSREとメルカリIBISの挑戦
0gm
0
630
レガシー共有バッチ基盤への挑戦 - SREドリブンなリアーキテクチャリングの取り組み
tatsukoni
0
180
しろおびセキュリティへ ようこそ
log0417
0
270
We Built for Predictability; The Workloads Didn’t Care
stahnma
0
130
Introduction to Bill One Development Engineer
sansan33
PRO
0
360
分析画面のクリック操作をそのままコード化 ! エンジニアとビジネスユーザーが共存するAI-ReadyなBI基盤
ikumi
0
130
Application Performance Optimisation in Practice (60 mins)
stevejgordon
0
110
顧客との商談議事録をみんなで読んで顧客解像度を上げよう
shibayu36
0
100
ブロックテーマでサイトをリニューアルした話 / 2026-01-31 Kansai WordPress Meetup
torounit
0
370
Webhook best practices for rock solid and resilient deployments
glaforge
1
120
Mosaic AI Gatewayでコーディングエージェントを配るための運用Tips / JEDAI 2026 新春 Meetup! AIコーディング特集
genda
0
150
GSIが複数キー対応したことで、俺達はいったい何が嬉しいのか?
smt7174
3
130
Featured
See All Featured
VelocityConf: Rendering Performance Case Studies
addyosmani
333
24k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
Paper Plane (Part 1)
katiecoart
PRO
0
3.8k
AI Search: Where Are We & What Can We Do About It?
aleyda
0
6.9k
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2k
A Soul's Torment
seathinner
5
2.2k
RailsConf 2023
tenderlove
30
1.3k
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
2
410
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
5
720
Darren the Foodie - Storyboard
khoart
PRO
2
2.3k
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
50
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ϥΠϑΛ
͝੩ௌ ͋Γ͕ͱ͏͍͟͝·ͨ͠