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
Electronによるアプリケーション開発事情2018 / builderscon2018
Search
h3poteto
September 07, 2018
Technology
9
10k
Electronによるアプリケーション開発事情2018 / builderscon2018
builderscon tokyo 2018『Electronによるアプリケーション開発事情2018』
h3poteto
September 07, 2018
Tweet
Share
More Decks by h3poteto
See All by h3poteto
EKS on Fargateは最高のJob基盤 / jawsug_bgnr
h3poteto
1
980
Kubernetes上で単発のジョブを実行するkube-jobというツールを作った / kubernetesmeetuptokyo22
h3poteto
6
8.3k
fluentdサーバをchefで構築するの辛かったけどDockerも別に救世主じゃなかった / tokyu ruby kaigi 12
h3poteto
0
4.6k
ECSのサービスをslack botでデプロイする // ecs-goploy
h3poteto
1
5.4k
まだRailsで消耗してるの?
h3poteto
7
4.8k
阿澄佳奈と昇竜拳
h3poteto
1
510
Other Decks in Technology
See All in Technology
専門分化が進む分業下でもユーザーが本当に欲しかったものを追求するプロダクトマネジメント/Focus on real user needs despite deep specialization and division of labor
moriyuya
0
890
ソフトウェア開発プロジェクトでの品質管理への提案(温故知新)
yohwada
0
100
反脆弱性(アンチフラジャイル)とデータ基盤構築
cuebic9bic
2
160
Amazon Q Developerを活用したアーキテクチャのリファクタリング
k1nakayama
2
170
隙間時間で爆速開発! Claude Code × Vibe Coding で作るマニュアル自動生成サービス
akitomonam
3
250
Segment Anything Modelの最新動向:SAM2とその発展系
tenten0727
0
180
dipにおけるSRE変革の軌跡
dip_tech
PRO
1
220
Kiroでインフラ要件定義~テスト を実施してみた
nagisa53
3
290
2時間で300+テーブルをデータ基盤に連携するためのAI活用 / FukuokaDataEngineer
sansan_randd
0
120
【2025 Japan AWS Jr. Champions Ignition】点から線、線から面へ〜僕たちが起こすコラボレーション・ムーブメント〜
amixedcolor
1
120
【CEDEC2025】『Shadowverse: Worlds Beyond』二度目のDCG開発でゲームをリデザインする~遊びやすさと競技性の両立~
cygames
PRO
1
280
Tableau API連携の罠!?脱スプシを夢見たはずが、逆に依存を深めた話
cuebic9bic
3
200
Featured
See All Featured
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
46
7.5k
The World Runs on Bad Software
bkeepers
PRO
70
11k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
30
2.2k
Fantastic passwords and where to find them - at NoRuKo
philnash
51
3.4k
Embracing the Ebb and Flow
colly
86
4.8k
Done Done
chrislema
185
16k
Optimizing for Happiness
mojombo
379
70k
The Power of CSS Pseudo Elements
geoffreycrofte
77
5.9k
Building an army of robots
kneath
306
45k
For a Future-Friendly Web
brad_frost
179
9.9k
A Modern Web Designer's Workflow
chriscoyier
695
190k
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 ΫϥΠΞϯτ