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
Stimulus × Jest × Direct Upload × Image Fluxで カ...
Search
Masayoshi Tokumoto
June 29, 2019
Technology
1
350
Stimulus × Jest × Direct Upload × Image Fluxで カオスなJS環境と画像アップロード機能を改善しつつユーザーの投稿率を上げた話
沖縄で開催されたハッカーズチャンプルー2019でLTをした時の資料です
Masayoshi Tokumoto
June 29, 2019
Tweet
Share
More Decks by Masayoshi Tokumoto
See All by Masayoshi Tokumoto
プロダクト・人・チームをいい感じにするためのシステム思考
sasumasa
0
44
RxJS と Netflix から学ぶリアクティブプログラミング
sasumasa
0
24
GraphQL を完全に理解する
sasumasa
0
26
キャパを超えた大型プロジェクトから学んだこと
sasumasa
0
1.3k
RailsエンジニアがStimulus + 生JSだけで約半年のプロジェクトを終えた今思うこと
sasumasa
0
330
IKUSEI on Rails
sasumasa
2
1.9k
文系から半年でRuby(Sinatra, Rails)を学んだら人生変わった@沖縄Ruby会議02
sasumasa
9
19k
Other Decks in Technology
See All in Technology
Evangelismo técnico: ¿qué, cómo y por qué?
trishagee
0
360
VideoMamba: State Space Model for Efficient Video Understanding
chou500
0
190
Why App Signing Matters for Your Android Apps - Android Bangkok Conference 2024
akexorcist
0
130
DynamoDB でスロットリングが発生したとき/when_throttling_occurs_in_dynamodb_short
emiki
0
230
SREが投資するAIOps ~ペアーズにおけるLLM for Developerへの取り組み~
takumiogawa
1
350
個人でもIAM Identity Centerを使おう!(アクセス管理編)
ryder472
3
220
OCI Vault 概要
oracle4engineer
PRO
0
9.7k
適材適所の技術選定 〜GraphQL・REST API・tRPC〜 / Optimal Technology Selection
kakehashi
1
660
マルチモーダル / AI Agent / LLMOps 3つの技術トレンドで理解するLLMの今後の展望
hirosatogamo
37
12k
強いチームと開発生産性
onk
PRO
35
11k
Incident Response Practices: Waroom's Features and Future Challenges
rrreeeyyy
0
160
DynamoDB でスロットリングが発生したとき_大盛りver/when_throttling_occurs_in_dynamodb_long
emiki
1
400
Featured
See All Featured
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
8
890
Designing for humans not robots
tammielis
250
25k
Keith and Marios Guide to Fast Websites
keithpitt
409
22k
Building Better People: How to give real-time feedback that sticks.
wjessup
364
19k
Adopting Sorbet at Scale
ufuk
73
9.1k
Teambox: Starting and Learning
jrom
133
8.8k
Thoughts on Productivity
jonyablonski
67
4.3k
Mobile First: as difficult as doing things right
swwweet
222
8.9k
Embracing the Ebb and Flow
colly
84
4.5k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
38
1.8k
Designing on Purpose - Digital PM Summit 2013
jponch
115
7k
Put a Button on it: Removing Barriers to Going Fast.
kastner
59
3.5k
Transcript
Stimulus × Jest × Direct Upload × Image FluxͰ ΧΦεͳJSڥͱը૾ΞοϓϩʔυػೳΛ
վળͭͭ͠ϢʔβʔͷߘΛ্͛ͨ ·͞ʢ@Masah201707ʣ
ࣗݾհ • ·͞ʢ@Masah201707ʣ • גࣜձࣾΈΜͳͷΣσΟϯάʢ18ଔʣ • ͪΐͬͱॻ͚Δ • Ruby/Rails/JavaScript/Stimulus •
͜Ε͔Βͪΐͬͱॻ͚Δ • React/Go • ͓ञͱ͓ण࢘ͱֶͼʹͳΔٕज़ͷ͕͋Ε͍͍ͩͨͤ
ΈΜͳͷΣσΟϯάͱ • ʮ݁ࠗࣜͷຊΛ͑ΔʯͨΊͷαʔϏε • ϝΠϯίϯςϯπʹ݁ࠗࣜʹؔ͢Δޱίϛɾ࣮ࡍͷඅ༻໌ࡉͳͲ͕͋Δ
ͬͨ͜ͱ Ϣʔβʔߘը૾ͷ ΞοϓϩʔυͷΈΛม͑Δ
Γ͍ͨ͜ͱ • jQueryΛ٫͍ͨ͠ʢͻͲ͍ίʔυͷւ͕͕͓ͬͯ Γɺςετͮ͠Β͍ʣ • ϢʔβʔΛ͍ؒͨͤΔ͜ͱͳ͘࠷େ10ຕͷը૾ ΞοϓϩʔυΛ࣮ݱ͍ͤͨ͞ • Ϣʔβʔ͕Ξοϓϩʔυͨ͠ը૾Λ৭ʑͳίϯςϯπ Ͱ͏ͨΊʹ৭ʑͳαΠζʹม͍ͨ͠
Γ͍ͨ͜ͱ • jQueryΛ٫͍ͨ͠ʢͻͲ͍ίʔυͷւ͕͕͓ͬͯ Γɺςετͮ͠Β͍ʣ • ϢʔβʔΛ͍ؒͨͤΔ͜ͱͳ͘࠷େ10ຕͷը૾ ΞοϓϩʔυΛ࣮ݱ͍ͤͨ͞ • Ϣʔβʔ͕Ξοϓϩʔυͨ͠ը૾Λ৭ʑͳίϯςϯπ Ͱ͏ͨΊʹ৭ʑͳαΠζʹม͍ͨ͠
ղܾࡦ Stimulus + Jest
Stimulus • Basecamp͕ࣾग़͍ͯ͠Δʮ߇͑Ίͳ৺ʯΛ࣋ͬͨϑ ϨʔϜϫʔΫ • HTMLͱJavaScriptΛdataଐੑͰܨ͙ • HTMLΛݟΔ͚ͩͰͲͷΑ͏ͳৼΔ͍Λ͢Δͷ͔͕Θ͔Δ • ಉ͡తͷίʔυΛάϧʔϓԽͤ͞ΔͷͰɺࣗͷίʔυ͕
ʮJavaScriptͷւʯʹຒΕΔͷΛ͙ • DOMͷϥΠϑαΠΫϧΛཧ͢Δ
Jest • FacebookJavaScriptςετπʔϧ • Reactͱͷੑߴͦ͏ • ಋೖָ͕ͦ͏ʢZero Configurationʣ • RSpecΈ͍ͨͰॻ͖ํʹ͠Έ͕͋Δ
const sum = require('./sum'); test('adds 1 + 2 to equal 3', () => { expect(sum(1, 2)).toBe(3); });
Γ͍ͨ͜ͱ • jQueryΛ٫͍ͨ͠ʢͻͲ͍ίʔυͷւ͕͕͓ͬͯ Γɺςετͮ͠Β͍ʣ • ϢʔβʔΛ͍ؒͨͤΔ͜ͱͳ͘࠷େ10ຕͷը૾ ΞοϓϩʔυΛ࣮ݱ͍ͤͨ͞ • Ϣʔβʔ͕Ξοϓϩʔυͨ͠ը૾Λ৭ʑͳίϯςϯπ Ͱ͏ͨΊʹ৭ʑͳαΠζʹม͍ͨ͠
͜Ε·Ͱͷը૾Ξοϓϩʔυ ΦϦδφϧը૾ͱ αϜωΠϧΛΞοϓϩʔυ • αϜωΠϧը૾ͷ࡞ • EXIFใͷमਖ਼ 1ຕͣͭը૾ΛΞοϓϩʔυ Amazon EC2
Amazon S3
S3ͷDirect Upload ॺ໊͖ͭURLΛ dataଐੑͱͯ͠ηοτ ෳͷը૾Λ ඇಉظͰΞοϓϩʔυ access_key_idͱ secret_access_keyΛऔಘ ̍ ̎
̏ Amazon EC2 Amazon S3 IAM
Γ͍ͨ͜ͱ • jQueryΛ٫͍ͨ͠ʢͻͲ͍ίʔυͷւ͕͕͓ͬͯ Γɺςετͮ͠Β͍ʣ • ϢʔβʔΛ͍ؒͨͤΔ͜ͱͳ͘࠷େ10ຕͷը૾ ΞοϓϩʔυΛ࣮ݱ͍ͤͨ͞ • Ϣʔβʔ͕Ξοϓϩʔυͨ͠ը૾Λ৭ʑͳίϯςϯπ Ͱ͏ͨΊʹ৭ʑͳαΠζʹม͍ͨ͠
ैདྷͷߏ • ը૾มͷ͘͠Έ • ϦαΠζɾΫϩοϓɾը࣭ͷௐΩϟογϡػೳΛඋ͑Δ
ैདྷͷߏ • ɿӡ༻͕ൃੜ • ϛυϧΣΞͷߋ৽ΞϥʔτରԠ
S3ͷDirect Upload ॺ໊͖ͭURLΛ dataଐੑͱͯ͠ηοτ ෳͷը૾Λ ඇಉظͰΞοϓϩʔυ access_key_idͱ secret_access_keyΛऔಘ ̍ ̎
̏ Amazon EC2 Amazon S3 IAM &9*'ใΛ मਖ਼͍ͯ͠ͳ͍
ImageFluxͱ ̍ຕͷը૾Λͱʹը૾ͷ֦େॖখɺΓൈ͖ɺ߹ͳͲͰσ όΠεʹ࠷దԽ͞Εͨը૾Λ؆୯ʹੜ͠ɺߴ͔ͭߴ࣭Ͱ ৴͢ΔαʔϏε
ImageFluxར༻ޙͷߏ ը૾ॲཧΛ·ΔͬͱImageFluxʹ͓ͤ͢Δ͜ͱ Ͱը૾पΓͷӡ༻͔Βղ์͞ΕΔ
݁Ռ • ը૾ͷߘ 1.7ഒ • 30595ຕˠ52622ຕ ϦϦʔεޙ4ϲ݄ͷ૯ը૾ߘΛલಉ݄ͱൺֱ • मਖ਼֦ுʹڧ͍ઃܭʹͳͬͨ
ࣦഊஊ
Vanilla JSͷDOMੜ _createThumbnailField(data) { const thumbnailFieldList = document.querySelector(`.js_${this.category}-thumbnail-field-list`) const thumbnailFieldWrapper
= document.createElement('div') thumbnailFieldWrapper.dataset.controller = 'string-counter' thumbnailFieldWrapper.dataset.target = 'thumbnail-field.item' thumbnailFieldWrapper.dataset.stringCounterMax = 20 thumbnailFieldWrapper.className = 'post-pictures-attachments' const thumbnailFieldBackground = document.createElement('div') thumbnailFieldBackground.className = 'os1-container-background' thumbnailFieldBackground.classList.add('-background-color-gold') thumbnailFieldBackground.classList.add('-margin-bottom-M') const hiddenObjectKey = this.createHiddenObjectKey(data.objectKey) const hiddenCategory = this.createHiddenCategory() const hiddenContentType = this.createHiddenContentType('review') this._createReviewThumbnailField({ data, thumbnailFieldBackground, hiddenObjectKey, hiddenContentType, hiddenCategory, }) thumbnailFieldWrapper.appendChild(thumbnailFieldBackground) thumbnailFieldList.appendChild(thumbnailFieldWrapper) }
_createThumbnailField(data) { const thumbnailFieldList = document.querySelector(`.js_${this.category}-thumbnail-field-list`) const thumbnailFieldWrapper = document.createElement('div')
thumbnailFieldWrapper.dataset.controller = 'string-counter' thumbnailFieldWrapper.dataset.target = 'thumbnail-field.item' thumbnailFieldWrapper.dataset.stringCounterMax = 20 thumbnailFieldWrapper.className = 'post-pictures-attachments' const thumbnailFieldBackground = document.createElement('div') thumbnailFieldBackground.className = 'os1-container-background' thumbnailFieldBackground.classList.add('-background-color-gold') thumbnailFieldBackground.classList.add('-margin-bottom-M') const hiddenObjectKey = this.createHiddenObjectKey(data.objectKey) const hiddenCategory = this.createHiddenCategory() const hiddenContentType = this.createHiddenContentType('review') this._createReviewThumbnailField({ data, thumbnailFieldBackground, hiddenObjectKey, hiddenContentType, hiddenCategory, }) thumbnailFieldWrapper.appendChild(thumbnailFieldBackground) thumbnailFieldList.appendChild(thumbnailFieldWrapper) } Vanilla JSͷDOMੜ THIS IS ZIGOKU
ϦΞϧDOMͰԾʢతʣDOM 1. ςϯϓϨʔτΛViewϑΝΠϧʹஔ͍͓ͯ͘ 2. MutationObserverͰಛఆͷHTMLཁૉΛࢹ 3. ը૾ΞοϓϩʔυޙʹඞཁͳใΛͦͷHTMLཁૉͷ attributesͱͯ͠ηοτ 4. MutationObserver͕Ԡ͠ɺςϯϓϨʔτͷCloneʹͦ
ΕͧΕͷΛೖΕͨͷΛAppend
ՆͷΠϯλʔϯγοϓ ։࠵͠·͢ʂ
ΈΜͳͷΣσΟϯά ՆͷΠϯλʔϯ in ԭೄ ࣌ɿ8݄22ɾ23ʢ༧ఆʣ ձɿླྀٿେֶֶ෦ ࣮ࡍͷαʔϏεʹػೳΛՃͯ͠ RubyͱRailsͷجຊΛֶ΅͏ʂ ৄ͘͠connpass (https://mwed.connpass.com/)
Ͱ 21ଔ͚
͋Γ͕ͱ͏͍͟͝·ͨ͠