Nuxt.js + FirebaseでWebアプリにチャット機能の導入する際に 工夫した点、感じたメリット・デメリットについてお話します。 その他には、フロント周りでボトルネックになっていた処理を調査し、高速化した話をする予定です。
Nuxt.js + Firebaseでの開ൃと高速化に挑んだ話鈴木孝之
View Slide
"HFOEBࣗݾհɾձࣾհ'JSFCBTFಋೖʹ͋ͨͬͯͷܦҢ'JSFCBTFͷಋೖɻͦΕ͔Βͷݒ೦ɾվળϏϧυߴԽͰͬͨࣄ
ࣗݾհɾձࣾհ
0.ࣗݾհ◆໊લླ ೭(Suzuki Takayuki)※ಉಉ໊ଟͯ͘ࠔͬͯ·͢ɻɻɻ◆ࣗݾհɾ1990ɺਆಸݝੜ·Εɻɾࣾձਓʹͳ͔ͬͯΒɺϓϩάϥϛϯάΛ࢝ΊΔɻɾ2015ʹϑϧεϐʔυʹೖࣾ͠ɺ2017ʹಠཱɻɾݱࡏɺडୗ։ൃΛΓͭͭɺࣗࣾWebαʔϏεΛ։ൃதɻ◆झຯίεϓϨɺԻָϥΠϒɺϚϥιϯେձʹग़Δɺٿ؍ઓ◆εΩϧPHP,Symfony2,CakePHP3,Laravel5,JavaScript,backbone.js,Angular.js
0.ࣗݾհ
Copyright Re:Build.inc All Rights Reserved.ձࣾհ◆ձ໊ࣾגࣜձࣾRe:Build◆ॅॴԭೄݝԭೄࢢதԝ̍ஸ̍̒−̕◆ࣄۀ༰ɾࣗࣾWEBαʔϏεͷاըɾ։ൃɻɾडୗ։ൃ◆ࣾһ6໊◆ΤϯδχΞͷಇ͖ํϦϞʔτϫʔΫՄೳͳࣗ༝ͳಇ͖ํΛਪͯ͠·͢ʂ
7ࣗࣾ։ൃνʔϜߏSuzuki Takayukiਖ਼ࣾһ(ि5ۈ)Kakazu Yuki(ਖ਼ࣾһ)Ϛωδϝϯτ&։ൃ։ൃϑϦʔϥϯε(ि2ۈ)ϑϦʔϥϯε(ि2ۈ)ϑϦʔϥϯε(ि2ۈ)ϑϦʔϥϯε(ि1ۈ)ཁ݅ఆٛUI/UXਖ਼ࣾһ(ि5ۈ)෭ۀ(ि1ۈ)͜ͷϙδγϣϯΛͬͯ·͢ʂ
'JSFCBTFಋೖʹ͋ͨͬͯͷܦҢ
9ࣗࣾWebαʔϏεͷ։ൃɾαʔϏε໊Tadoru https://tadoru.work/ ɾγεςϜ֓ཁΤϯδχΞಉ࢜ͷࣄհίϛϡχςΟ
Re:Buildاۀͷ୲ऀ͕ΤʔδΣϯτΛબͿΤʔδΣϯτ͕ࣗͷܨ͕Γͷ͋ΔΤϯδχΞ·ͨνʔϜʹΛ͔͚ΔΤʔδΣϯτࣄલʹ৹੍ࠪϫʔΧʔΤʔδΣϯτاۀϏδωεϞσϧ࠾༻ใुεΩϧܦݧՔಇঢ়گεΩϧܦݧՔಇঢ়گεΩϧܦݧՔಇঢ়گࣄΛհ͢Δ˕̋̋×˕̋×̋̋
11બఆٕͨ͠ज़■ٕज़ཁ݅ɾαʔόαΠυPHP(Laravel5.8)ɾϑϩϯτΤϯυJavaScript(Vue.js,Nuxt.js)ɾςετPHPUnit,Cypressɾ੩తղੳESlint,PHPStanɾΠϯϑϥAWS(EC2,S3,RDS(mariadb))ɾ։ൃڥphp7,nginx,mariadb,docker,webpackɾͦͷଞgitlab,gitlabCI(ࣗಈσϓϩΠͳͲ),Slack,phpStorm
ϑϩϯτΤϯυ αʔόαΠυશମߏGitlab CIϥΠϒϥϦͳͲFirebaseϥΠϒϥϦͳͲ
શମͷΞʔΩςΫνϟ(̐ͭͷυϝΠϯผ)ϑϩϯτΤϯυ αʔόαΠυbladeMPAߏϑϩϯτΤϯυ αʔόαΠυSPAߏαʔόαΠυϑϩϯτΤϯυ αʔόαΠυbladeMPAߏϫʔΧʔը໘ ΤʔδΣϯτը໘اۀը໘SPAߏϑϩϯτΤϯυӡӦը໘MPASPA
νϟοτػೳͷ࣮ݱํ๏ΛٞWebSocketɺϩϯάϙʔϦϯάɺFirebaseͷͲΕΛ͏͔ʁɾஅج४- ࣮қ͕ͦ͜·Ͱߴ͘ͳ͍ɻ͋͘·Ͱεϐʔυॏࢹɻ- ϝϯςφϯείετ͕͍ɻ- ޙʑɺϝοηʔδͷจݴΛղੳͯ͠ੳ͢ΔՄೳੑ͋Γɻ- ࠾༻ͷϦʹͳΔΑ͏ͳٕज़ͩͱঘྑ͍ɻ
ϩϯάϙʔϦϯάͷௐࠪ݁ՌɾLong pollingͱʁݹయతͳํ๏ͰɺҰఆ࣌ؒ͝ͱʹαʔόʹߋ৽Λ͍߹ΘͤΔख๏ɻϖʔδશମΛऔಘ͢ΔͱߴෛՙͱͳΔͨΊɺAjax௨৴ͰϦΫΤετ͠มߋ෦Λߋ৽͢Δͷ͕࠷ۙͰओྲྀɻΫϥΠΞϯτ͔Βૹ৴͞ΕͨϦΫΤετΛαʔό͕͍ͬͨΜอཹ͠ɺαʔόଆͰΠϕϯτ͕ൃੜͨ͠ࡍʹҙͷλΠϛϯάͰϨεϙϯεΛฦ͢ख๏ɻϦΞϧλΠϜੑߴ͍ɻແବͳ͍߹Θͤൃੜ͠ͳ͍͕ɺ࣌ؒHTTPίωΫγϣϯΛ༗ͯ͠͠·͏ɻҰΫϥΠΞϯτʹPushͨ͠Βɺ·ͨΫϥΠΞϯτ͔ΒͷϦΫΤετΛͨͳ͍ͱ͍͚ͳ͍ɻλΠϛϯάʹΑͬͯλΠϜϥά͕ൃੜ͢Δɻhttp://peacock.ky-3.net/realtime_notification/realtime_notification
ϩϯάϙʔϦϯάͷ࣮ྫhttp://peacock.ky-3.net/realtime_notification/realtime_notification
WebSocketௐࠪ݁ՌɾWebsocketHTTPΛ֦ுͨ͠ϦΞϧλΠϜ௨৴Λલఏͱͯ͠ํʹσʔλ͕ૹड৴Ͱ͖Δ௨৴ϓϩτίϧͷ͜ͱɻখ͞ͳσʔλαΠζͰใΛૹड৴Ͱ͖ΔͨΊHTTPʹൺΔͱ͔ͳΓ௨৴ίετ͕͍ɻTCPίωΫγϣϯΛுΓͬͺͳ͠ʹ͢ΔͨΊɺϊϯϒϩοΩϯάI/OαʔόʢNode.jsʣ͕ඞཁɻ
Laravel EchoͰ࣮ݱ͢Δ߹http://crought.com/blog/%E3%80%90laravel%E3%81%A7%E7%B0%A1%E6%98%93%E3%83%81%E3%83%A3%E3%83%83%E3%83%88%E3%80%911-%E3%83%81%E3%83%A3%E3%83%83%E3%83%88%E6%A9%9F%E8%83%BD%E3%81%AE%E4%BB%95%E7%B5%84%E3%81%BF%E3%81%AE%E7%90%86-173/Լهͷهࣄ͔ΒҾ༻
Laravel EchoͰ࣮ݱ͢Δ߹http://crought.com/blog/%E3%80%90laravel%E3%81%A7%E7%B0%A1%E6%98%93%E3%83%81%E3%83%A3%E3%83%83%E3%83%88%E3%80%911-%E3%83%81%E3%83%A3%E3%83%83%E3%83%88%E6%A9%9F%E8%83%BD%E3%81%AE%E4%BB%95%E7%B5%84%E3%81%BF%E3%81%AE%E7%90%86-173/ͦ͠͏…ʂ
Firebaseௐࠪ݁Ռαʔόෛՙ ಋೖίετ ϝϯςφϯείετFirebase ͋·Γ͔͔Βͳ͍ Ί গͳ͍ϩϯάϙʔϦϯά ͔͔Δ Ί ී௨WebSocket ͋·Γ͔͔Βͳ͍ ߴΊ ଟΊ
ٞͷ݁ՌFirebaseʹܾఆʂʂɾબఆཧ༝- αϯϓϧΛ࡞ͬͯΈͨ࣌ʹ͘Β͍Ͱ࣮Ͱ͖ͨɻ- ผҊ݅Ͱ࡞ͬͨϝοηʔδػೳ͕1ਓ݄΄Ͳ͔͚࣮͕ͯͨ͠ɺόά͕ଟ͘ϝϯςφϯείετΛԼ͔͛ͨͬͨɻ- LaravelEcho(Websocket)ϩϯάϙʔϦϯάͰ࣮ͨ͠Β͚ͬ͜͏͕͔͔Γͦ͏ͩͬͨɻ- ࠾༻ͷϦʹͳΓͦ͏ɻ
FirebaseಋೖલͰͷݒ೦- Firebase্ͷDatabaseͷແྉ͕1GB͔͠ͳ͍- ίϨΫγϣϯؒͰ֎෦ΩʔΛ࣋ͨͤΒΕͳ͍ɻ- ݕࡧ݅ʹҰ෦ɺ੍ݶ͋Γɻ
'JSFCBTFͷಋೖɻͦΕ͔Βͷݒ೦ɾվળ
FirestoreͷߏusersίϨΫγϣϯ roomsίϨΫγϣϯ
usersίϨΫγϣϯίϨΫγϣϯͷJSONߏྫFirebaseͷFireStoreྫ
roomsίϨΫγϣϯίϨΫγϣϯͷJSONߏྫFirebaseͷFireStoreྫ
ը໘Πϝʔδ(MPA)
ը໘Πϝʔδ(MPA)νϟοτ෦͚ͩVue.jsͷίϯϙʔωϯτΛ༻Index.vueRoomCreateForm.vueMessages.vueRooms.vue
ը໘Πϝʔδ(SPA)
ը໘Πϝʔδ(SPA)Index.vueRoomCreateForm.vueMessages.vueRooms.vueνϟοτ෦ྲྀ༻ͯ͠ɺશମNuxt.jsΛ༻
ҰൠϢʔβը໘ͷߏLaravelͷbladeRoomCreateForm.vueMessages.vueRooms.vueUserCreateForm.vueIndex.vueFirebase Tadoru DBFirebaseʹϩάΠϯϢʔβΛొ͢ΔϧʔϜΛ࡞͢Δνϟοτ૬खΛऔಘ͢ΔϧʔϜϝϯόʔใΛऔಘ͢ΔϝοηʔδҰཡΛऔಘ͢ΔϝοηʔδΛૹ৴͢ΔϧʔϜҰཡΛऔಘ͢Δ
اۀϢʔβը໘ͷߏpages/chat/index.vueRoomCreateForm.vueMessages.vueRooms.vueUserCreateForm.vueIndex.vueFirebase Tadoru DBFirebaseʹϩάΠϯϢʔβΛొ͢ΔϧʔϜΛ࡞͢Δνϟοτ૬खΛऔಘ͢ΔϧʔϜϝϯόʔใΛऔಘ͢ΔϝοηʔδҰཡΛऔಘ͢ΔϝοηʔδΛૹ৴͢ΔϧʔϜҰཡΛऔಘ͢Δ
γʔέϯεਤ ʙ ϧʔϜ࡞ʙ
γʔέϯεਤ ʙ ϧʔϜ࡞ʙϧʔϜ࡞࣌ʹClound FuctionͰUsersͷαϒίϨΫγϣϯʹॻ͖ࠐΈʹ͍͘
3 9Google Cloud Functions for Firebasehttp://furandon-pig.hatenablog.com/entry/2014/06/04/215727Cloud Functions for Firebase Λ͏͜ͱͰɺΠϕϯτυϦϒϯͳΞϓϦέʔγϣϯΛ࡞͢Δ͜ͱ͕Ͱ͖·͢ɻ SMS ϝοηʔδͷૹ৴ͳͲͷॲཧͷΑ͏ͳ֎෦αʔϏε࿈ܞͳͲΛߦ͏͜ͱ͕ՄೳʹͳΓ·͢ɻ·ͨɺΫϥΠΞϯτΞϓϦέʔγϣϯʹ࣮ͤ͞Δʹॏͨ͗͢ΔΑ͏ͳॲཧΛ Cloud Functions for Firebase ʹҕͶΔ͜ͱ͕Ͱ͖·͢ɻ
functionͷॲཧUsersͷαϒίϨΫγϣϯʹroomsΛॻ͖ࠐΈ
UsersʹαϒίϨΫγϣϯΛ࣋ͨͤͨཧ༝- Ҏલ(20193݄͝Ζ)ͷΓํͩͱݕࡧ͕ࠔͩͬͨͱࢥͬͨͷͰɺͦ͏͍ͯͨ͠- ࠓΫΤϦ͕؆୯ʹͰ͖Δ͔͠Εͳ͍https://speakerdeck.com/koogawa/firestore-falsedetashe-ji-nituite?slide=17
γʔέϯεਤ ʙ ϧʔϜҰཡɺϝοηʔδҰཡΛऔಘʙ
Users͔ΒroomsͷใΛऔಘγʔέϯεਤ ʙ ϧʔϜҰཡɺϝοηʔδҰཡΛऔಘʙ
usersͷαϒίϨΫγϣϯ͔ΒroomsΛऔಘUsers͝ͱͷID͝ͱʹରͷroomsΛαϒίϨΫγϣϯ͔Βऔಘ͢Δ
֤มߋΛײͯ͠ɺνϟοτใΛߋ৽https://firebase.google.com/docs/firestore/query-data/listen?hl=ja
Ϣʔβͷొ࣌ͷॳظϑϩʔDBʹϢʔβొFirebaseTadoru DBϢʔβใΛొϢʔβใΛొFirestoreʹϢʔβొgRPCͰૹΔཧ͕໘ʹͳΔ͕DBͱFirestoreʹϢʔβใ͕̎ͭग़དྷΔࣄʹͳͬͯ͠·ͬͨ…ɻPHPͷFirestoreͷϥΠϒϥϦ͕gRPCࢦఆͩͬͨLaravelͷΦϒβʔόͰFirestoreͷొॲཧൃಈ
PHPଆ͔ΒUserใొ࣌ʹΦϒβʔόʔͰFiresotreʹొgRPCͷΠϯετʔϧඞཁͳͷͰɺཁҙ
ӡ༻ޙͷݒ೦ ʙ Clound Function͕͍ ʙϝοηʔδϧʔϜͷॳظىಈ࣌
ӡ༻ޙͷݒ೦ ʙ Clound Function͕͍ ʙϝοηʔδϧʔϜͷ2ճҎ߱ͷىಈ࣌
Clound Function͕͍ཧ༝firebaseͷcloud functions͕࣮ߦ͞ΕΔ·Ͱͷ͕࣌ؒҟ༷ʹ͍ɻτϦΨʔͷ݅Λຬ͔ͨͯ͠Βɺ5ඵલޙ͔͔͔ͬͯΒσʔλʹ࣮ߦ݁Ռ͕ө͞ΕΔ͜ͱ͕͋Δɻcloud functionsʹҰఆظؒͷΞΫηε͕ͳ͍߹ɺࣗಈతʹΠϯελϯε͕εϦʔϓϞʔυʹೖΔɻhttps://qiita.com/Masaaki/items/54cf16c6c55cdae91b82
ղܾࡦಛʹͳ͠ɻසൟʹϦΫΤετ͕ૹΒΕ͍ͯΔ߹ɺࠓճͷൃੜ͠ͳ͍ͣͳͷͰɺ։ൃڥಛ༗ͷͰ͋Δɻຊ൪ڥͰΠϯελϯε͕ఀࢭ͢Δ͜ͱͳ͍ͣͳͷͰɺେͨ͠ʹͳΒͳ͍ɻhttps://qiita.com/Masaaki/items/54cf16c6c55cdae91b82
ϏϧυߴԽͰͬͨࣄ
8FCQBDL#VOEMF"OBMZ[FSͱʁԼهΛՄࢹԽͯ͘͠ΕΔɻɾwebpackͷվળͷҝɺ͍loaderpluginΛΓ͍ͨɾόϯυϧϑΝΠϧͷαΠζΛݮΒ͍ͨ͠ͷͰɺόϯυϧϑΝΠϧͷ֤ύοέʔδ͕Ͳͷ͘Β͍ͷ༰ྔΛΊ͍ͯΔ͔Γ͍ͨhttps://github.com/webpack-contrib/webpack-bundle-analyzer
࣮ߦํ๏
8FCQBDL#VOEMF"OBMZ[FSͱʁhttps://qiita.com/kurosame/items/9e7092cdf08ff2ba7500
ݱঢ়ͷ՝ᶃChart.js͕ॏ͍ᶄmoment.js͕ॏ͍- locale͕ແବʹଟ͍ᶅlodash.js͕ॏ͍
ᶃChart.js͕ॏ͍ɾvue-chart.jsͷதͰΘΕ͍ͯΔͷͰɺ֎͢ͷͦ͠͏ͩͬͨɻ
ᶄmoment.js͕ॏ͍nuxt.config.jsʹmomentͷઃఆΛՃ
ᶅlodash.js͕ॏ͍ɾݱঢ়ɺσΟʔϓίϐʔͷՕॴʹ͔͠lodash.js͕ΘΕ͍ͯͳ͔ͬͨ
ᶅlodash.js͕ॏ͍https://kuroeveryday.blogspot.com/2017/05/deep-clone-object-in-javascript.htmlੜͷJSͰσΟʔϓίϐʔͰ͖Δ͕ɺ͜Ε࣮֬ʹͰ͖͍ͯΔ͔ո͍͠Β͍͠ɻ
ᶅlodash.js͕ॏ͍https://qiita.com/hareku/items/d9f92c96697163356bd3lodashΛimport _ from 'lodash'ͷΑ͏ʹಡΈࠐΜͰ͠·͏ͱɺશͯͷlodashؔͳͲ͕bundle͞Εͯ͠·͍·͢ɻͦΕΛճආ͢ΔͨΊɺ༻͢ΔؔͷΈΛimport͢ΔΑ͏ʹมߋ͠·͢ɻ
վળ݁Ռ lodashͱmoment.js΄΅ফ͑ͨʂ
վળ݁Ռ 1MBܰྔԽ
·ͱΊ
- FirebaseࢥͬͨΑΓಋೖ͢Δʹ͋ͨͬͯɺ͕͔͔ͬͨ- FirebaseΛೖΕͯগ͠ෳࡶͳΞʔΩςΫνϟʹͳͬͯ͠·ͬͨ(ݟ͕͋ΕճආͰ͖͔ͨ͠Εͳ͍)- ϏϧυͷߴԽ͢Δʹ͋ͨͬͯɺmoment.jslodash.js͕ॏ͘ͳΔͷΑ͋͘Γͦ͏·ͱΊ