Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Electronによるアプリケーション開発事情2018 / builderscon2018
Search
h3poteto
September 07, 2018
Technology
11k
9
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Electronによるアプリケーション開発事情2018 / builderscon2018
builderscon tokyo 2018『Electronによるアプリケーション開発事情2018』
h3poteto
September 07, 2018
More Decks by h3poteto
See All by h3poteto
EKS on Fargateは最高のJob基盤 / jawsug_bgnr
h3poteto
1
1.1k
Kubernetes上で単発のジョブを実行するkube-jobというツールを作った / kubernetesmeetuptokyo22
h3poteto
6
9.1k
fluentdサーバをchefで構築するの辛かったけどDockerも別に救世主じゃなかった / tokyu ruby kaigi 12
h3poteto
0
5.3k
ECSのサービスをslack botでデプロイする // ecs-goploy
h3poteto
1
6k
まだRailsで消耗してるの?
h3poteto
7
5k
阿澄佳奈と昇竜拳
h3poteto
1
600
Other Decks in Technology
See All in Technology
生成AIで高い生産性を求められて、 悩み、乗り越えた話
mot_techtalk
2
130
生成AIを使って「人が」考える技術 ― AI時代の人機共想と実践ノウハウ|UNITT AC2026
ishiirikie
0
550
[2026-09-30]ロックンロールは鳴り止まないっ - 信頼性かまってちゃん - 「データ駆動を投げ捨ててまで。」追いかける信頼性改善に向けた取り組みの話
tosite
0
200
Swap and Memory Reclaim - Squeezing Out More RAM
ennael
PRO
1
1.6k
20260930_Gemma4_Hands-on
tsho
0
220
私の推しは「聞いてから進む」AIです -AI-DLCに一人でアプリを作らせた話
yama3133
1
170
大阪オフィスに Unitree Go2 がやってきたので Physical AI やってみた
dafujii
0
300
購入ドメインでの課題と取り組み
ykagano
0
130
「とりあえず動く」の先へ。 AI時代のチーム開発と内部設計/2026-slsdays
slsops
0
140
個別開発で終わらせない。 現場の課題をプロダクトの強さに変える StockmarkのFDE
ktkrhr
0
580
Snowflake Horizon Catalog と Apache Iceberg で作る オープンなデータ基盤
kitagawaz
0
440
Claude起点の仕様駆動開発
tanakaseiya
0
370
Featured
See All Featured
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
2
6.3k
Building an army of robots
kneath
307
47k
WCS-LA-2024
lcolladotor
0
840
The Curious Case for Waylosing
cassininazir
1
550
Visualization
eitanlees
153
17k
The Spectacular Lies of Maps
axbom
PRO
1
1.1k
My Coaching Mixtape
mlcsv
0
340
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
340
Making Projects Easy
brettharned
120
6.8k
A Modern Web Designer's Workflow
chriscoyier
699
190k
sira's awesome portfolio website redesign presentation
elsirapls
0
440
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
1
620
Transcript
ElectronʹΑΔΞϓϦ έʔγϣϯ։ൃࣄ 2018 builderscon tokyo 2018 @h3_poteto
ࣗݾհ • Akira Fukushimaʢౡ ໌ʣ • github: h3poteto • twitter:
h3_poteto • Mastodon: @
[email protected]
• ࣄɿterraform৬ਓ@scouty
એ
None
σεΫτοϓ͚ͷ MastodonΫϥΠΞϯτΛ ࡞͍ͬͯ·͢
None
ࠓ͜ͷΞϓϦέʔγϣ ϯΛࡐʹElectronͷΛ ͠·͢
None
એऴΘΓ
ࠓͷ • ElectronͰΞϓϦέʔγϣϯ࡞ΔͷϚδͰָ ͩΑʢͲΜͲΜָʹͳΓͭͭ͋Δ • ͰSNSͷΫϥΠΞϯτ࡞Δͷେม • ւ֎͔Βͷҙ֎ͳԠ͋ͬͨ • ΈΜͳMastodonͬͯ΄͍͠
ElectronͰΞϓϦέʔγϣϯ Λ։ൃ͢Δ
Electron? • ੲAtom-shellͱݺΕ͍ͯͨ • Chromium + Node.js • Windows/Mac/Linux͚ͷΞϓϦέʔγϣϯ ͕࡞ΕΔ
ͭ·Γ • දࣔ෦ϒϥβͳͷͰWebϑϩϯτΤϯ υͷٕज़Λ͑Δ • React.js/Vue.jsࡌͤΒΕΔ • SPAͰΞϓϦ͕࡞ΕΔ
vue-cliͰܗ͕࡞ΕΔ $ npm install -g vue-cli $ vue init simulatedgreg/electron-vue
\ whalebird
vue-cliͰͷܗ • webpackʹΑΔ։ൃ࣌ͷϏϧυઃఆ • auto-reload • ςετͷܗ
Electronͷجຊߏ • mainϓϩηε: όοΫάϥϯυδϣϒɼΞϓ ϦέʔγϣϯͷཧΛߦ͏ • rendererϓϩηε: jsΛ࣮ߦ͠html, cssΛϨϯ μϦϯά͢Δ
rendererϓϩηεଆΛͯ͢ SPAʹ͢Δ͜ͱ͕Մೳ ͜͜ͰReact.js/Vue.js͕͑ Δ
خ͍͜͠ͱᶃ React.js/Vue.js(Flux)ΛGUI ΞϓϦέʔγϣϯͰ͑Δ
iOS։ൃ͍ͯͨ͜͠Ζ • ViewController͕ແݶʹଠΔʂ • delegate͕ͦ͜Βதʹ…… • ϞσϧͲ͏͜͏ͱ͍͏ΑΓঢ়ଶը໘ભҠͷ ϩδοΫ͕େม
None
class SwipeViewController: UIViewController, SwipeViewDelegate, SwipeViewDataSource, UINavigationControllerDelegate, UITabBarControllerDelegate { func navigationController(_
navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) { if (type(of: viewController) === SwipeViewController.self) { for i in 0 ..< self.streamList.count() { self.viewItems[i].fCellSelect = false } } } } ͛͢ʔ͍ͬͺ͍Delegateͯ͠Δ
React.js/Vue.sj(Flux)ʹ͢Δͱ • ࠩϨϯμϦϯάReact.js/Vue.jsͷ͕ͬ ͯ͘ΕΔ͜ͱ͕લఏ • delegateͱ͔ඞཁͳ͍ • Flux͕σʔλͷྲྀΕΛҰํʹͯ͘͠ΕΔ • GUIΞϓϦέʔγϣϯͳͷʹݟ௨͕͠ྑ͍
<toot :message="message" :filter="filter" :focused="message.uri === focusedId" :overlaid="modalOpened" @update=“updateToot" @delete=“deleteToot" @focusNext="focusNext"
@focusPrev="focusPrev" @selectToot="focusToot(message)"> </toot> focusToot (message) { this.focusedId = message.uri }
خ͍͜͠ͱᶄ ίϯτϦϏϡʔλ͕૿͑Δ
WhalebirdͷίϯτϦϏϡʔλ • ΄΅jsͷٕज़ͳͷͰjsք۾ͷਓ͕ίϯτϦ Ϗϡʔτ͍͢͠ʢ͜͜ͷϘϦϡʔϜ͕ଟ͍
خ͍͜͠ͱᶅ ΫϩεϓϥοτϑΥʔϜ
ΫϩεϓϥοτϑΥʔϜ • Windows/Mac/LinuxͰಉ͡ιʔεͷ··Ϗϧ υՄೳ • ͨͩ͠Ұ෦Mac͚ͷػೳ࣮͞Ε͍ͯ Δ
ྫ: Dockϝχϡʔ ϝχϡʔ༰͕ ΧελϚΠζՄೳ elecron-context-menu
خ͍͜͠ͱᶆ ΞΫςΟϒʹ։ൃ͞Ε͍ͯΔ
ElectronͷϦϦʔεׂͱ׆ൃ • v2.0.8 - 2018/08/23 • v2.0.7 - 2018/08/09 •
v2.0.6 - 2018/08/01 3.0.0४උத: v3.0.0-beta.8
ΞϓϦέʔγϣϯΛύοέʔ δϯάˍϦϦʔε
Let’s ElectronΈ͍ͨͳهࣄ ͍ͬͺ͍͋Δ͚ͲϦϦʔεʹ ؔ͢Δهࣄ͕΄ͱΜͲͳ͍
֮͑ͯ΄͍͜͠ͱ: electron-builder͕͋Εͩ ͍͍ͨղܾ͢Δ
• electron-packager • electron-builder ͱ͍͏ͷ͕͋Δ
electron-packager • webpackͰίϯύΠϧ͞ΕͨϑΝΠϧ܈ΛΞ ϓϦέʔγϣϯͱͯ͠·ͱΊΔ • جຊతʹ͜Ε͔ͬͯ͘͠Εͳ͍ • ίϚϯυϥΠϯ
electron-builder • ΞϓϦέʔγϣϯͷύοέʔδϯά • ূ໌ॻͷՃ • ֤छΠϯετʔϧՄೳͳϑΝΠϧܗࣜʹѹॖ ʢ.dmg, .deb, .rpm,
.exeʣ • package.jsonʹઃఆ͕ॻ͚Δ • ެࣜυΩϡϝϯτ͕๛: https://www.electron.build/
"build": { "productName": "Whalebird", "appId": "org.whalebird.desktop", "directories": { "output": "build"
}, "mac": { "icon": "build/icons/icon.icns", "target": [ "dmg" ], "category": "public.app-category.social-networking" },
͓͔͛ͰϦϦʔεܗ͕ࣜ๛ • AppStore(.pkg) • .dmg • .exe • .deb •
.rpm • .tar.bz2 • snapcraft (.snap)
ͪΐͬͱಛघͳઃఆྫ • ΞΠίϯ • ֎෦ϦιʔεʢԻʣ • ূ໌ॻ • MASʢMac App
Storeʣ
ΞΠίϯ • Mac/Windows: Ϗϧυ࣌ʹຒΊࠐΉ • Linux: Ұ෦main.jsͰ֎෦ϑΝΠϧΛࢦఆ • ը૾ϑΝΠϧasarѹॖ͞Ε͍ͯͯ෦ͷ ͷΛࢦఆՄೳ
"build": { "productName": “Whalebird", "files": [ "dist/electron/**/*", "build/icons/*" ], "mac":
{ "icon": "build/icons/icon.icns", "target": [ "dmg" ], "category": "public.app-category.social-networking" }, "win": { "icon": "build/icons/icon.ico", "target": "nsis" }, iconͷࢦఆ
mainWindow = new BrowserWindow({ titleBarStyle: 'hidden', useContentSize: true, icon: path.resolve(__dirname,
'../../build/icons/256x256.png') } BrowserWindowͷ ىಈΦϓγϣϯͰΞΠίϯΛࢦఆ
֎෦ϦιʔεͷಡΈࠐΈ • ԻϑΝΠϧΛಡΈࠐΈ͍ͨ߹͕͋Δ • asarѹॖͷϑΝΠϧಡΈऔΕͳ͍ • ϏϧυઃఆͰasarѹॖ͔Βআ֎͢Δඞཁ͕͋ Δ
"build": { "productName": "Whalebird", "appId": "org.whalebird.desktop", "directories": { "output": "build"
}, "extraResources": [ "build/sounds/*" ], "files": [ "dist/electron/**/*", "build/icons/*" ], ԻΛextraResources ʹࢦఆ
const soundBasePath = process.env.NODE_ENV === 'development' ? path.join(__dirname, '../../build/sounds/') :
path.join(process.resourcesPath, 'build/sounds/') const sound = path.join(soundBasePath, 'operation_sound01.wav') simplayer(sound, (err) => { if (err) log.error(err) }) ͜͜asar֎ͷϑΝΠϧΛ ࢦఆ͢Δඞཁ͕͋Δ
Mac༻ͷূ໌ॻ • Developer ID Installer • Developer ID Application electron-builderͳΒϏϧυ࣌ʹ
KeyChainAccessͷূ໌ॻΛ ࣗಈͰͯͯ͘ΕΔ
MAS͚ͩಛผѻ͍ • electron-builderͰCodeSign·ͰͰ͖ͳ͔ͬͨ • electron-packagerͰϏϧυޙɼࣗͰCodeSign • plistΛࣗͰॻ͘ඞཁ͕͋Δ • ͦΕΛApplication LoaderͰΞοϓϩʔυ͢Δ
• ͋ͱiTunes ConnectͰόʔδϣϯΞοϓ
#!/bin/zsh -f # Name of your app. APP="Whalebird" # The
path of your app to sign. APP_PATH="./packages/Whalebird-mas-x64/Whalebird.app" # The path to the location you want to put the signed package. RESULT_PATH="./packages/$APP.pkg" # The name of certificates you requested. APP_KEY="3rd Party Mac Developer Application: Akira Fukushima (HB4N6B2YVM)" INSTALLER_KEY="3rd Party Mac Developer Installer: Akira Fukushima (HB4N6B2YVM)" # The path of your plist files. CHILD_PLIST="./plist/child.plist" PARENT_PLIST="./plist/parent.plist" LOGINHELPER_PLIST="./plist/loginhelper.plist" FRAMEWORKS_PATH="$APP_PATH/Contents/Frameworks" # At first, rename app.asar.unpacked directory. # Because electron-builder does not store app.asar.unpacked directory. # I want to store unpacked files at the same directory as electron-builder. mv $APP_PATH/Contents/Resources/app.asar.unpacked/* $APP_PATH/Contents/Resources/ codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/ Electron Framework" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/ Libraries/libffmpeg.dylib" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/ Libraries/libnode.dylib" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper.app/Contents/MacOS/$APP Helper" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper.app/" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper EH.app/Contents/MacOS/$APP Helper EH" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper EH.app/" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper NP.app/Contents/MacOS/$APP Helper NP" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper NP.app/" codesign -s "$APP_KEY" -f --entitlements "$LOGINHELPER_PLIST" "$APP_PATH/Contents/Library/LoginItems/$APP Login Helper.app/Contents/MacOS/$APP Login Helper" codesign -s "$APP_KEY" -f --entitlements "$LOGINHELPER_PLIST" "$APP_PATH/Contents/Library/LoginItems/$APP Login Helper.app/" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$APP_PATH/Contents/MacOS/$APP" codesign -s "$APP_KEY" -f --entitlements "$PARENT_PLIST" "$APP_PATH" productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$RESULT_PATH"
#!/bin/zsh -f # Name of your app. APP="Whalebird" # The
path of your app to sign. APP_PATH="./packages/Whalebird-mas-x64/Whalebird.app" # The path to the location you want to put the signed package. RESULT_PATH="./packages/$APP.pkg" # The name of certificates you requested. APP_KEY="3rd Party Mac Developer Application: Akira Fukushima (HB4N6B2YVM)" INSTALLER_KEY="3rd Party Mac Developer Installer: Akira Fukushima (HB4N6B2YVM)" # The path of your plist files. CHILD_PLIST="./plist/child.plist" PARENT_PLIST="./plist/parent.plist" LOGINHELPER_PLIST="./plist/loginhelper.plist" FRAMEWORKS_PATH="$APP_PATH/Contents/Frameworks" # At first, rename app.asar.unpacked directory. # Because electron-builder does not store app.asar.unpacked directory. # I want to store unpacked files at the same directory as electron-builder. mv $APP_PATH/Contents/Resources/app.asar.unpacked/* $APP_PATH/Contents/Resources/ codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/ Electron Framework" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/ Libraries/libffmpeg.dylib" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/ Libraries/libnode.dylib" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper.app/Contents/MacOS/$APP Helper" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper.app/" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper EH.app/Contents/MacOS/$APP Helper EH" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper EH.app/" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper NP.app/Contents/MacOS/$APP Helper NP" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper NP.app/" codesign -s "$APP_KEY" -f --entitlements "$LOGINHELPER_PLIST" "$APP_PATH/Contents/Library/LoginItems/$APP Login Helper.app/Contents/MacOS/$APP Login Helper" codesign -s "$APP_KEY" -f --entitlements "$LOGINHELPER_PLIST" "$APP_PATH/Contents/Library/LoginItems/$APP Login Helper.app/" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$APP_PATH/Contents/MacOS/$APP" codesign -s "$APP_KEY" -f --entitlements "$PARENT_PLIST" "$APP_PATH" productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$RESULT_PATH" codesignίϚϯυΛ͑ྑ͍
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://
www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.security.app-sandbox</key> <true/> <key>com.apple.security.application-groups</key> <string>HB4N6B2YVM.org.whalebird.desktop</string> <key>com.apple.security.files.user-selected.read-only</key> <true/> <key>com.apple.security.network.client</key> <true/> </dict> </plist>
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://
www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.security.app-sandbox</key> <true/> <key>com.apple.security.application-groups</key> <string>HB4N6B2YVM.org.whalebird.desktop</string> <key>com.apple.security.files.user-selected.read-only</key> <true/> <key>com.apple.security.network.client</key> <true/> </dict> </plist> ͜͜Ͱ • ωοτϫʔΫΞΫηε • ϑΝΠϧΞΫηε ΛڐՄ͢Δ
͜ͷ͋ͱ৹͕ࠪ͋Δʂ
MAS݁ߏͭΒ͍
͜͜·Ͱͷ·ͱΊ • electron-builderϚδΜΓ • electron-builderͷਐา͕͍ͷͰ͜Εͬͱ ͚ؒҧ͍ͳ͍ • MAS͍ͭେม
MastodonͷΫϥΠΞϯτΛ ࡞Δ
ͳͥMastodonͷ ΫϥΠΞϯτΛ࡞Δͷ͔
σεΫτοϓ͚ͷ ΫϥΠΞϯτ͕ͳ͍ɼຊʹগͳ͍ • MstdnʢࣗͰjsonϑΝΠϧΛ༻ҙͯ͠token ΛೖΕΔʣ • The Desk • TsuruʢόΠφϦͷͳ͍ʣ
ͳ͍ͷͰ͋Ε ࣗͰͭ͘Ζ͏
Whalebirdͷίϯηϓτ • LinuxͰ͑ΔͷΛ • Slackʹ׳Ε͍ͯΔͷͰSlackΆ͍ݟͨ • γϣʔτΧοτͱʹ͔͘ଟ͘ ࠷ڧͷTwitterΫϥΠΞϯτ ઓ૪Λࢥ͍ग़͢
ॳ൛͕Ͱ͖ͨ
ւ֎͔ΒͷԠ
ʢӳޠαϙʔτ͔ͨ͠Β͔ʣ ࠷ॳւ֎͔ΒԠ͕
ϦϦʔεͯ͠࠷ॳͷҰिؒ
None
None
None
None
ྑ͍ʂ͚ͩͲElectron͔…… Έ͍ͨͳԠ͔Γ
ͦΜͳʹElectronͬͯධѱ ͍ͷʁ ຊͰ͋·Γฉ͔ͳ͔͚ͬͨͬͲ
ධͷѱ͞ • ϝϞϦফඅ͕ଟ͍ • SlackΛىಈ͢Δ͚ͩͰ500MBҎ্ϝϞϦΛ͍͔࣋ͬͯ ΕΔ • ࠷దԽ͞Εͯͳ͍ͷͰϝϞϦফඅ͕ଟ͍ • Javaͷํ͕͍ܰ
• node.js͕ݏ͍
ϝϞϦͱઓ͏
࠷ظ1GBҎ্ ͍͔࣋ͬͯΕͨ
Ͳ͜ͰϝϞϦΛ ফඅ͍ͯ͠Δͷ͔ʁ
ࢼͯ͠ΈΔ • StreamingΛࢭΊͨঢ়ଶͰ͍Ζ͍Ζ৮ͬͯΈΔ • StreamingΛࢭΊͨঢ়ଶͰ์ஔ ϝϞϦϦʔΫ͔ʁ
StreamingࢭΊ͍ͯΔͱ૿͑ ͳ͍ʂ ผʹϝϞϦϦʔΫ͍ͯ͠ΔΘ ͚Ͱͳ͍ʂ
StreamingʹΑΔϝϞϦফඅ • ຊΛ૿ͯ͠ΈΔʁ
StreamingʹΑΔϝϞϦফඅ • όοΫάϥϯυͰStreaming͢Δ͚ͩͰର ͯ͠ϝϞϦΛফඅ͠ͳ͍ʂ
͏গ͠ࢼ͢ • ྲྀͷ͍ΠϯελϯεͰ์ஔʢmikutterʣ • ྲྀͷ͍ΠϯελϯεͰ์ஔʢjpʣ
໌Β͔ʹྲྀ͕͍΄͏͕ ϝϞϦফඅ͕ଟ͍
͜Ε͠ϨϯμϦϯά ͳͷͰʁ
WhalebirdͷλΠϜϥΠϯඳը • Streaming͞ΕͨͷΛͯ͢htmlͱͯ͠දࣔ ͍ͯͨ͠ • ͭ·Γϒϥβͷ࣮ʹؙ͛ • FireFoxͰڊେϖʔδΛ։͍ͨΒॏ͍ ʢ͔ͩΒΈΜͳϖʔδωʔγϣϯ͢ΔΜͩ
None
ଞͲ͏͍ͯ͠Δͷ͔ʁ
iOSͷ߹ • UITableViewදࣔ͞Ε͍ͯΔ෦͔͠Ϩϯμ Ϧϯά͍ͯ͠ͳ͍ • ӅΕ͍ͯΔ·ͰؚΊͨεΫϩʔϧྔܭࢉ ͍ͯ͠Δ • εΫϩʔϧ͞Εͨࡍදࣔ͢Δલʹ༰Λ ϨϯμϦϯά
ਤ
දࣔ͞Ε͍ͯͳ͍෦ ϨϯμϦϯά͍ͯ͠ͳ͍
UITableViewController • cellForRowAt: ηϧͷதΛϨϯμϦϯά • heightForRowAt: ηϧͷߴ͞Λࢉग़ • estimatedHeightForRowAt: ະදࣔΛؚΊͯ
ηϧͷߴ͞Λࢉग़
ྲྀੴʹ͜ΕύΫΕͳ͍
ϙΠϯτɿ ඳը͢Δൣғݟ͍͑ͯΔ ෦͘Β͍Ͱे
ElectronͰͲ͏͢Δ͔ʁ • λΠϜϥΠϯΛͯ͢දࣔ͢ΔͷΛΊΔ • ࠷৽40݅ͷΈΛදࣔ͠ɼඞཁͰ͋Ε LazyLoading • StreamingͰߋ৽͞Εͨ߹ɼݹ͍ͷΛফ ͯ͠40݅ʹอͭ
None
εΫϩʔϧΠϕϯτΛͱʹ੍ޚͯ͠Δ
200MBΛΔʂ
ѹత͡Όͳ͍͔ʂ
ϙΠϯτɿ Vue.jsͷύϑΥʔϚϯεʹ ؾΛΔ
vue.jsͷύϑΥʔϚϯε • v-ifͱv-show • v-if: ସ࣌ʹhtml͕ੜ͞ΕϨϯμϦϯά͞ ΕΔ • v-show: ͡Ί͔ΒϨϯμϦϯά͞Ε͍ͯΔ
͕ɼdisplay: none͞Ε͍ͯΔ͚ͩ
v-ifͱv-show • v-ifͷସ࣌ϨϯμϦϯάίετഅࣛʹͳΒ ͳ͍ • ͔͠͠ɼඞཁͷͳ͍ͱ͜ΖΛv-showʹ͢Δͱ ͣͬͱϝϞϦΛফඅ͠ଓ͚Δ
͜͜ਖ਼ղ͕ͳ͍
࠷ۙͷWhalebird • ϝϞϦফඅ: 200MB ~ 500MB • 500MB͘Β͍·Ͱ͘ΔͱGC͞ΕͯϝϞϦফඅ ͕ҰؾʹݮΔ •
ը૾͕গͳ͍࣌ؒଳ͍ܰʂ ʢpawooͷਓ͝ΊΜͳ͍͞
࠷ۙͷWhalebird • ϕʔεʹͳ͍ͬͯΔElectronΛόʔδϣϯΞο ϓ͢ΔͱϝϞϦফඅ͕ݮΔ • ύϑΥʔϚϯεChromiumʹ߹ΘͤͯͲΜͲ Μྑ͘ͳΔ
͜ͷઌͷ࡞ઓ • ը૾ͷඇදࣔΦϓγϣϯ • τΡʔτ͕࿈ଓ͢Δ߹·ͱΊͯϨϯμϦ ϯάͰ͖ͳ͍͔ʁ
͓ӄ༷Ͱ࠷ۙͷԠྑ͍
APIΫϥΠΞϯτϥΠϒϥϦ Λࣗ࡞͢Δ
ॳmastodon-apiͱ͍͏ Node.jsͷϥΠϒϥϦΛར༻
͕ɼΤϥʔʹͳΔͱ͍͏ใࠂ ͕ͪΒ΄Β
mastodon-api • POSTύϥϝʔλΛbodyͰͳ͘urlύϥϝʔ λͱͯ͠ૹ৴͍ͯ͠Δ • Ұ෦αʔόͰͦΕΒ͕ڋ൱͞Ε͍ͯΔ ଞͷબࢶ͕ͳ͍
ͳ͍ͷͳΒࣗ࡞͠Α͏
None
megalodon • TypeScriptͰॻ͍ͨmastodonAPIΫϥΠΞϯ τϥΠϒϥϦ • Streaming࣮ࡁΈ • OAuthΞϓϦέʔγϣϯొ༻ϝιου༻ ҙ
public get<T>(path: string, params = {}): Promise<Response<T>> { return axios
.get<T>(this.baseUrl + path, { headers: { 'Authorization': `Bearer ${this.accessToken}` }, params }) .then((resp: AxiosResponse<T>) => { const res: Response<T> = { data: resp.data, status: resp.status, statusText: resp.statusText, headers: resp.headers } return res }) }
όάͬͯͨ߹ શ෦ࣗͰ࣏ͤΔ
ΠϯελϯεΛ ݐͯΔ͜ͱ͋Δ
ΠϯελϯεݪҼͷ͍߹Θͤ ଟ͍ • ϩάΠϯ͕Ͱ͖ͳ͍ • τΡʔτͰ͖ͳ͍ • Streaming͕ಈ͔ͳ͍ • ʑ……
࠷ۙ͋ͬͨ൵͍͠ࣄྫ • (mastodon͕͍ͬͯΔ)doorkeeper 4.3.0Ҏ ্ Ͱnative_redirect_uriʹؔ͢Δόά͕ࠞೖ • mastodon: doorkeeper ~>
4.4.1 • σεΫτοϓΞϓϦέʔγϣϯͰೝূ͕Ͱ͖ ͳ͘ͳΔ
͔֬ΊΔ&ϓϧϦΫΛग़͢ • खݩͰmastodonαʔόΛݐͯΔ: https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/ Development-guide.md • ࠶ݱͨ͠ • doorkeeperʹissueཱͯͨΓɼmastodonʹϓ
ϧϦΫΛૹͬͨΓ
None
ΫϥΠΞϯτ͚ͩͷͰͳ͍͜ͱ͕ଟ͍ͷͰɼ αΫοͱΠϯελϯεΛཱͯΒΕΔΑ͏ʹ ͓ͯ͘͠ͷॏཁ
·ͱΊ
ޭͨ͠ͳʔͱࢥ͏͜ͱ • ElectronͰ࡞ͬͨ͜ͱ • Vue.jsͱ͍͏બ • ӳޠݍͷྀ
ࣦഊͨ͠ͳʔͱࢥ͏͜ͱ • ͬͱૣ͘࡞ΕΑ͔ͬͨ • ͬͱૣ͘TypeScriptΛߟྀ͖ͩͬͨ͢ • megalodon(APIΫϥΠΞϯτ)ϝϯς͠ ͍͢ • దͳΦϒδΣΫτΛ͢͜ͱ͕ଟ͍
updateTimeFormat ({ dispatch, commit, state }, value) { const newGeneral
= Object.assign({}, state.general, { timeFormat: value }) const config = { general: newGeneral } ipcRenderer.send('update-preferences', config) ipcRenderer.once('error-update-preferences', (event, err) => { ipcRenderer.removeAllListeners('response-update-preferences') }) ipcRenderer.once('response-update-preferences', (event, conf) => { ipcRenderer.removeAllListeners('error-update-preferences') dispatch('App/loadPreferences', null, { root: true }) commit('updateGeneral', conf.general) }) }, actionͻͱ͔ͭ͠ҾΛऔΕͳ͍ mainͱͷ௨৴ipcͰߦ͏ ະͷΦϒδΣΫτ
શମతʹݟͯ • ElectronʢϦϦʔεํ๏ؚΊͯʣਐԽͯ͠ ͍ΔͷͰ͓͢͢Ί͍ͨ͠ • ϝϞϦফඅରࡦՄೳ • Vue.jsͰGUIΞϓϦέʔγϣϯ։ൃ͢Δͷྑ ͍
Mastodon͕ շదʹͳͬͨͷͰ TwitterΛݟΔ͜ͱ͕ݮͬͨ
͞Α͏ͳΒTwitter ΫϥΠΞϯτ