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.6k
Reactのパフォーマンスを改善する必要がなかった話
現在開発中の自社製品に対し、パフォーマンスを初めて意識した際にまだ特に大きく改善する点が見当たらなかったというだけの話
teamspirit_minato
May 26, 2017
Tweet
Share
Other Decks in Technology
See All in Technology
Open Table Format (OTF) が必要になった背景とその機能 (2025.10.28)
simosako
3
620
触れるけど壊れないWordPressの作り方
masakawai
0
650
可観測性は開発環境から、開発環境にもオブザーバビリティ導入のススメ
layerx
PRO
4
2.6k
CloudComposerによる大規模ETL 「制御と実行の分離」の実践
leveragestech
0
160
組織全員で向き合うAI Readyなデータ利活用
gappy50
5
2.1k
Amazon Q Developer CLIをClaude Codeから使うためのベストプラクティスを考えてみた
dar_kuma_san
0
320
kotlin-lsp の開発開始に触発されて、Emacs で Kotlin 開発に挑戦した記録 / kotlin‑lsp as a Catalyst: My Journey to Kotlin Development in Emacs
nabeo
2
290
dbtとAIエージェントを組み合わせて見えたデータ調査の新しい形
10xinc
7
1.8k
今から間に合う re:Invent 準備グッズと現地の地図、その他ラスベガスを周る際の Tips/reinvent-preparation-guide
emiki
1
250
GPUをつかってベクトル検索を扱う手法のお話し~NVIDIA cuVSとCAGRA~
fshuhe
0
370
SREのキャリアから経営に近づく - Enterprise Risk Managementを基に -
shonansurvivors
1
720
GCASアップデート(202508-202510)
techniczna
0
260
Featured
See All Featured
Navigating Team Friction
lara
190
15k
Unsuck your backbone
ammeep
671
58k
RailsConf 2023
tenderlove
30
1.3k
What's in a price? How to price your products and services
michaelherold
246
12k
Context Engineering - Making Every Token Count
addyosmani
8
330
It's Worth the Effort
3n
187
28k
Agile that works and the tools we love
rasmusluckow
331
21k
Product Roadmaps are Hard
iamctodd
PRO
55
11k
Visualization
eitanlees
150
16k
Why You Should Never Use an ORM
jnunemaker
PRO
60
9.6k
Mobile First: as difficult as doing things right
swwweet
225
10k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.1k
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ϥΠϑΛ
͝੩ௌ ͋Γ͕ͱ͏͍͟͝·ͨ͠