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
360
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
59
RxJS と Netflix から学ぶリアクティブプログラミング
sasumasa
0
44
GraphQL を完全に理解する
sasumasa
0
38
キャパを超えた大型プロジェクトから学んだこと
sasumasa
0
1.4k
RailsエンジニアがStimulus + 生JSだけで約半年のプロジェクトを終えた今思うこと
sasumasa
0
340
IKUSEI on Rails
sasumasa
2
1.9k
文系から半年でRuby(Sinatra, Rails)を学んだら人生変わった@沖縄Ruby会議02
sasumasa
9
19k
Other Decks in Technology
See All in Technology
COVESA VSSによる車両データモデルの標準化とAWS IoT FleetWiseの活用
osawa
1
370
Codeful Serverless / 一人運用でもやり抜く力
_kensh
7
450
「何となくテストする」を卒業するためにプロダクトが動く仕組みを理解しよう
kawabeaver
0
420
Django's GeneratedField by example - DjangoCon US 2025
pauloxnet
0
150
バイブスに「型」を!Kent Beckに学ぶ、AI時代のテスト駆動開発
amixedcolor
2
580
普通のチームがスクラムを会得するたった一つの冴えたやり方 / the best way to scrum
okamototakuyasr2
0
110
Android Audio: Beyond Winning On It
atsushieno
0
2.4k
スクラムガイドに載っていないスクラムのはじめかた - チームでスクラムをはじめるときに知っておきたい勘所を集めてみました! - / How to start Scrum that is not written in the Scrum Guide 2nd
takaking22
1
120
実践!カスタムインストラクション&スラッシュコマンド
puku0x
0
490
現場で効くClaude Code ─ 最新動向と企業導入
takaakikakei
1
260
共有と分離 - Compose Multiplatform "本番導入" の設計指針
error96num
2
1.1k
react-callを使ってダイヤログをいろんなとこで再利用しよう!
shinaps
2
260
Featured
See All Featured
Building Applications with DynamoDB
mza
96
6.6k
Automating Front-end Workflow
addyosmani
1370
200k
[RailsConf 2023] Rails as a piece of cake
palkan
57
5.8k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
For a Future-Friendly Web
brad_frost
180
9.9k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Git: the NoSQL Database
bkeepers
PRO
431
66k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.1k
Faster Mobile Websites
deanohume
309
31k
Agile that works and the tools we love
rasmusluckow
330
21k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
7
850
YesSQL, Process and Tooling at Scale
rocio
173
14k
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ଔ͚
͋Γ͕ͱ͏͍͟͝·ͨ͠