Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Electronによるアプリケーション開発事情2018 / builderscon2018

h3poteto
September 07, 2018

Electronによるアプリケーション開発事情2018 / builderscon2018

builderscon tokyo 2018『Electronによるアプリケーション開発事情2018』

h3poteto

September 07, 2018
Tweet

More Decks by h3poteto

Other Decks in Technology

Transcript

  1. ElectronʹΑΔΞϓϦ
    έʔγϣϯ։ൃࣄ৘
    2018
    builderscon tokyo 2018
    @h3_poteto

    View Slide

  2. ࣗݾ঺հ
    • Akira Fukushimaʢ෱ౡ ໌ʣ
    • github: h3poteto
    • twitter: h3_poteto
    • Mastodon: @[email protected]
    • ࢓ࣄɿterraform৬ਓ@scouty

    View Slide

  3. એ఻

    View Slide

  4. View Slide

  5. σεΫτοϓ޲͚ͷ
    MastodonΫϥΠΞϯτΛ
    ࡞͍ͬͯ·͢

    View Slide

  6. View Slide

  7. ࠓ೔͸͜ͷΞϓϦέʔγϣ
    ϯΛ୊ࡐʹElectronͷ࿩Λ
    ͠·͢

    View Slide

  8. View Slide

  9. એ఻ऴΘΓ

    View Slide

  10. ࠓ೔ͷ࿩
    • ElectronͰΞϓϦέʔγϣϯ࡞ΔͷϚδͰָ
    ͩΑʢͲΜͲΜָʹͳΓͭͭ͋Δ
    • Ͱ΋SNSͷΫϥΠΞϯτ࡞Δͷ͸େม
    • ւ֎੎͔Βͷҙ֎ͳ൓Ԡ͋ͬͨ
    • ΈΜͳMastodon΍ͬͯ΄͍͠

    View Slide

  11. ElectronͰΞϓϦέʔγϣϯ
    Λ։ൃ͢Δ

    View Slide

  12. Electron?
    • ੲ͸Atom-shellͱݺ͹Ε͍ͯͨ
    • Chromium + Node.js
    • Windows/Mac/Linux޲͚ͷΞϓϦέʔγϣϯ
    ͕࡞ΕΔ

    View Slide

  13. ͭ·Γ
    • දࣔ෦෼͸ϒϥ΢βͳͷͰWebϑϩϯτΤϯ
    υͷٕज़Λ࢖͑Δ
    • React.js/Vue.js΋ࡌͤΒΕΔ
    • SPAͰΞϓϦ͕࡞ΕΔ

    View Slide

  14. vue-cliͰ਽ܗ͕࡞ΕΔ
    $ npm install -g vue-cli
    $ vue init simulatedgreg/electron-vue \
    whalebird

    View Slide

  15. vue-cliͰͷ਽ܗ
    • webpackʹΑΔ։ൃ࣌ͷϏϧυઃఆ
    • auto-reload
    • ςετͷ਽ܗ

    View Slide

  16. Electronͷجຊߏ଄
    • mainϓϩηε: όοΫάϥ΢ϯυδϣϒɼΞϓ
    Ϧέʔγϣϯͷ؅ཧΛߦ͏
    • rendererϓϩηε: jsΛ࣮ߦ͠html, cssΛϨϯ
    μϦϯά͢Δ

    View Slide

  17. rendererϓϩηεଆΛ͢΂ͯ
    SPAʹ͢Δ͜ͱ͕Մೳ
    ͜͜ͰReact.js/Vue.js͕࢖͑
    Δ

    View Slide

  18. خ͍͜͠ͱᶃ
    React.js/Vue.js(Flux)ΛGUI
    ΞϓϦέʔγϣϯͰ࢖͑Δ

    View Slide

  19. iOS։ൃ͍ͯͨ͜͠Ζ
    • ViewController͕ແݶʹଠΔʂ
    • delegate͕ͦ͜Βதʹ……
    • ϞσϧͲ͏͜͏ͱ͍͏ΑΓঢ়ଶ΍ը໘ભҠͷ
    ϩδοΫ͕େม

    View Slide

  20. View Slide

  21. 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ͯ͠Δ

    View Slide

  22. React.js/Vue.sj(Flux)ʹ͢Δͱ
    • ࠩ෼ϨϯμϦϯά͸React.js/Vue.jsͷ૚͕΍ͬ
    ͯ͘ΕΔ͜ͱ͕લఏ
    • delegateͱ͔ඞཁͳ͍
    • Flux͕σʔλͷྲྀΕΛҰํ޲ʹͯ͘͠ΕΔ
    • GUIΞϓϦέʔγϣϯͳͷʹݟ௨͕͠ྑ͍

    View Slide

  23. :message="message"
    :filter="filter"
    :focused="message.uri === focusedId"
    :overlaid="modalOpened"
    @update=“updateToot"
    @delete=“deleteToot"
    @focusNext="focusNext"
    @focusPrev="focusPrev"
    @selectToot="focusToot(message)">

    focusToot (message) {
    this.focusedId = message.uri
    }

    View Slide

  24. خ͍͜͠ͱᶄ
    ίϯτϦϏϡʔλ͕૿͑Δ

    View Slide

  25. WhalebirdͷίϯτϦϏϡʔλ
    • ΄΅jsͷٕज़ͳͷͰjsք۾ͷਓ͕ίϯτϦ
    Ϗϡʔτ͠΍͍͢ʢ͜͜ͷϘϦϡʔϜ͕ଟ͍

    View Slide

  26. خ͍͜͠ͱᶅ
    ΫϩεϓϥοτϑΥʔϜ

    View Slide

  27. ΫϩεϓϥοτϑΥʔϜ
    • Windows/Mac/LinuxͰಉ͡ιʔεͷ··Ϗϧ
    υՄೳ
    • ͨͩ͠Ұ෦Mac޲͚ͷػೳ౳΋࣮૷͞Ε͍ͯ
    Δ

    View Slide

  28. ྫ: Dockϝχϡʔ
    ϝχϡʔ಺༰͕
    ΧελϚΠζՄೳ
    elecron-context-menu

    View Slide

  29. خ͍͜͠ͱᶆ
    ΞΫςΟϒʹ։ൃ͞Ε͍ͯΔ

    View Slide

  30. 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

    View Slide

  31. ΞϓϦέʔγϣϯΛύοέʔ
    δϯάˍϦϦʔε

    View Slide

  32. Let’s ElectronΈ͍ͨͳهࣄ͸
    ͍ͬͺ͍͋Δ͚ͲϦϦʔεʹ
    ؔ͢Δهࣄ͕΄ͱΜͲͳ͍

    View Slide

  33. ֮͑ͯ΄͍͜͠ͱ:
    electron-builder͕͋Ε͹ͩ
    ͍͍ͨղܾ͢Δ

    View Slide

  34. • electron-packager
    • electron-builder
    ͱ͍͏ͷ͕͋Δ

    View Slide

  35. electron-packager
    • webpackͰίϯύΠϧ͞ΕͨϑΝΠϧ܈ΛΞ
    ϓϦέʔγϣϯͱͯ͠·ͱΊΔ
    • جຊతʹ͜Ε͔͠΍ͬͯ͘Εͳ͍
    • ίϚϯυϥΠϯ

    View Slide

  36. electron-builder
    • ΞϓϦέʔγϣϯͷύοέʔδϯά
    • ূ໌ॻͷ௥Ճ
    • ֤छΠϯετʔϧՄೳͳϑΝΠϧܗࣜʹѹॖ
    ʢ.dmg, .deb, .rpm, .exe౳ʣ
    • package.jsonʹઃఆ͕ॻ͚Δ
    • ެࣜυΩϡϝϯτ͕๛෋: 

    https://www.electron.build/

    View Slide

  37. "build": {
    "productName": "Whalebird",
    "appId": "org.whalebird.desktop",
    "directories": {
    "output": "build"
    },
    "mac": {
    "icon": "build/icons/icon.icns",
    "target": [
    "dmg"
    ],
    "category": "public.app-category.social-networking"
    },

    View Slide

  38. ͓͔͛ͰϦϦʔεܗ͕ࣜ๛෋
    • AppStore(.pkg)
    • .dmg
    • .exe
    • .deb
    • .rpm
    • .tar.bz2
    • snapcraft (.snap)

    View Slide

  39. ͪΐͬͱಛघͳઃఆྫ
    • ΞΠίϯ
    • ֎෦ϦιʔεʢԻ੠౳ʣ
    • ূ໌ॻ
    • MASʢMac App Storeʣ

    View Slide

  40. ΞΠίϯ
    • Mac/Windows: Ϗϧυ࣌ʹຒΊࠐΉ
    • Linux: Ұ෦͸main.jsͰ֎෦ϑΝΠϧΛࢦఆ
    • ը૾ϑΝΠϧ͸asarѹॖ͞Ε͍ͯͯ΋಺෦ͷ΋
    ͷΛࢦఆՄೳ

    View Slide

  41. "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ͷࢦఆ

    View Slide

  42. mainWindow = new BrowserWindow({
    titleBarStyle: 'hidden',
    useContentSize: true,
    icon: path.resolve(__dirname, '../../build/icons/256x256.png')
    }
    BrowserWindowͷ
    ىಈΦϓγϣϯͰΞΠίϯΛࢦఆ

    View Slide

  43. ֎෦ϦιʔεͷಡΈࠐΈ
    • Ի੠ϑΝΠϧ౳ΛಡΈࠐΈ͍ͨ৔߹͕͋Δ
    • asarѹॖ಺ͷϑΝΠϧ͸ಡΈऔΕͳ͍
    • ϏϧυઃఆͰasarѹॖ͔Βআ֎͢Δඞཁ͕͋
    Δ

    View Slide

  44. "build": {
    "productName": "Whalebird",
    "appId": "org.whalebird.desktop",
    "directories": {
    "output": "build"
    },
    "extraResources": [
    "build/sounds/*"
    ],
    "files": [
    "dist/electron/**/*",
    "build/icons/*"
    ],
    Ի੠ΛextraResources
    ʹࢦఆ

    View Slide

  45. 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֎ͷϑΝΠϧΛ
    ࢦఆ͢Δඞཁ͕͋Δ

    View Slide

  46. Mac༻ͷূ໌ॻ
    • Developer ID Installer
    • Developer ID Application
    electron-builderͳΒϏϧυ࣌ʹ
    KeyChainAccess಺ͷূ໌ॻΛ
    ࣗಈͰ౰ͯͯ͘ΕΔ

    View Slide

  47. MAS͚ͩ͸ಛผѻ͍
    • electron-builderͰCodeSign·ͰͰ͖ͳ͔ͬͨ
    • electron-packagerͰϏϧυޙɼࣗ෼ͰCodeSign
    • plistΛࣗ෼Ͱॻ͘ඞཁ͕͋Δ
    • ͦΕΛApplication LoaderͰΞοϓϩʔυ͢Δ
    • ͋ͱ͸iTunes ConnectͰόʔδϣϯΞοϓ

    View Slide

  48. #!/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"

    View Slide

  49. #!/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ίϚϯυΛ࢖͑͹ྑ͍

    View Slide





  50. com.apple.security.app-sandbox

    com.apple.security.application-groups
    HB4N6B2YVM.org.whalebird.desktop
    com.apple.security.files.user-selected.read-only

    com.apple.security.network.client



    View Slide





  51. com.apple.security.app-sandbox

    com.apple.security.application-groups
    HB4N6B2YVM.org.whalebird.desktop
    com.apple.security.files.user-selected.read-only

    com.apple.security.network.client



    ͜͜Ͱ
    • ωοτϫʔΫΞΫηε
    • ϑΝΠϧΞΫηε
    ౳ΛڐՄ͢Δ

    View Slide

  52. ͜ͷ͋ͱ৹͕ࠪ͋Δʂ

    View Slide

  53. MAS͸݁ߏͭΒ͍

    View Slide

  54. ͜͜·Ͱͷ·ͱΊ
    • electron-builderϚδ΂ΜΓ
    • electron-builderͷਐา͕଎͍ͷͰ͜Ε࢖ͬͱ
    ͚͹ؒҧ͍ͳ͍
    • MAS͸͍ͭ΋େม

    View Slide

  55. MastodonͷΫϥΠΞϯτΛ
    ࡞Δ

    View Slide

  56. ͳͥMastodonͷ
    ΫϥΠΞϯτΛ࡞Δͷ͔

    View Slide

  57. σεΫτοϓ޲͚ͷ
    ΫϥΠΞϯτ͕ͳ͍ɼຊ౰ʹগͳ͍
    • Mstdnʢࣗ෼ͰjsonϑΝΠϧΛ༻ҙͯ͠token
    ΛೖΕΔʣ
    • The Desk
    • TsuruʢόΠφϦͷ഑෍͸ͳ͍ʣ

    View Slide

  58. ͳ͍ͷͰ͋Ε͹
    ࣗ෼Ͱͭ͘Ζ͏

    View Slide

  59. Whalebirdͷίϯηϓτ
    • LinuxͰ࢖͑Δ΋ͷΛ
    • Slackʹ׳Ε͍ͯΔͷͰSlackΆ͍ݟͨ໨
    • γϣʔτΧοτ͸ͱʹ͔͘ଟ͘
    ࠷ڧͷTwitterΫϥΠΞϯτ
    ઓ૪Λࢥ͍ग़͢

    View Slide

  60. ॳ൛͕Ͱ͖ͨ

    View Slide

  61. ւ֎͔Βͷ൓Ԡ

    View Slide

  62. ʢӳޠαϙʔτ͔ͨ͠Β͔ʣ
    ࠷ॳ͸ւ֎͔Β൓Ԡ͕

    View Slide

  63. ϦϦʔεͯ͠࠷ॳͷҰिؒ

    View Slide

  64. View Slide

  65. View Slide

  66. View Slide

  67. View Slide

  68. ྑ͍ʂ͚ͩͲElectron͔……
    Έ͍ͨͳ൓Ԡ͹͔Γ

    View Slide

  69. ͦΜͳʹElectronͬͯධ൑ѱ
    ͍ͷʁ
    ೔ຊͰ͸͋·Γฉ͔ͳ͔͚ͬͨͬͲ

    View Slide

  70. ධ൑ͷѱ͞
    • ϝϞϦফඅ͕ଟ͍
    • SlackΛىಈ͢Δ͚ͩͰ500MBҎ্ϝϞϦΛ͍͔࣋ͬͯ
    ΕΔ
    • ࠷దԽ͞Εͯͳ͍ͷͰϝϞϦফඅ͕ଟ͍
    • Javaͷํ͕͍ܰ
    • node.js͕ݏ͍

    View Slide

  71. ϝϞϦͱઓ͏

    View Slide

  72. ࠷੝ظ͸1GBҎ্
    ͍͔࣋ͬͯΕͨ

    View Slide

  73. Ͳ͜ͰϝϞϦΛ
    ফඅ͍ͯ͠Δͷ͔ʁ

    View Slide

  74. ࢼͯ͠ΈΔ
    • StreamingΛࢭΊͨঢ়ଶͰ͍Ζ͍Ζ৮ͬͯΈΔ
    • StreamingΛࢭΊͨঢ়ଶͰ์ஔ
    ϝϞϦϦʔΫ͔ʁ

    View Slide

  75. StreamingࢭΊ͍ͯΔͱ૿͑
    ͳ͍ʂ
    ผʹϝϞϦϦʔΫ͍ͯ͠ΔΘ
    ͚Ͱ͸ͳ͍ʂ

    View Slide

  76. StreamingʹΑΔϝϞϦফඅ
    • ຊ਺Λ૿΍ͯ͠ΈΔʁ

    View Slide

  77. StreamingʹΑΔϝϞϦফඅ
    • όοΫάϥ΢ϯυͰStreaming͢Δ͚ͩͰ͸ର
    ͯ͠ϝϞϦΛফඅ͠ͳ͍ʂ

    View Slide

  78. ΋͏গ͠ࢼ͢
    • ྲྀ଎ͷ஗͍ΠϯελϯεͰ์ஔʢmikutterʣ
    • ྲྀ଎ͷ଎͍ΠϯελϯεͰ์ஔʢjpʣ

    View Slide

  79. ໌Β͔ʹྲྀ଎͕଎͍΄͏͕
    ϝϞϦফඅ͕ଟ͍

    View Slide

  80. ͜Ε͸΋͠΍ϨϯμϦϯά
    ͳͷͰ͸ʁ

    View Slide

  81. WhalebirdͷλΠϜϥΠϯඳը
    • Streaming͞Εͨ΋ͷΛ͢΂ͯhtmlͱͯ͠දࣔ
    ͍ͯͨ͠
    • ͭ·Γ͸ϒϥ΢βͷ࣮૷ʹؙ౤͛
    • FireFoxͰ΋ڊେϖʔδΛ։͍ͨΒॏ͍

    ʢ͔ͩΒΈΜͳϖʔδωʔγϣϯ͢ΔΜͩ

    View Slide

  82. View Slide

  83. ଞ͸Ͳ͏͍ͯ͠Δͷ͔ʁ

    View Slide

  84. iOSͷ৔߹
    • UITableView͸දࣔ͞Ε͍ͯΔ෦෼͔͠Ϩϯμ
    Ϧϯά͍ͯ͠ͳ͍
    • ӅΕ͍ͯΔ෼·ͰؚΊͨεΫϩʔϧྔ͸ܭࢉ
    ͍ͯ͠Δ
    • εΫϩʔϧ͞Εͨࡍ͸දࣔ͢Δ௚લʹ಺༰Λ
    ౎౓ϨϯμϦϯά

    View Slide


  85. View Slide

  86. දࣔ͞Ε͍ͯͳ͍෦෼͸
    ϨϯμϦϯά͍ͯ͠ͳ͍

    View Slide

  87. UITableViewController
    • cellForRowAt: ηϧͷத਎ΛϨϯμϦϯά
    • heightForRowAt: ηϧͷߴ͞Λࢉग़
    • estimatedHeightForRowAt: ະදࣔ෼ΛؚΊͯ
    ηϧͷߴ͞Λࢉग़

    View Slide

  88. ྲྀੴʹ͜Ε͸ύΫΕͳ͍

    View Slide

  89. ϙΠϯτɿ
    ඳը͢Δൣғ͸ݟ͍͑ͯΔ
    ෦෼͘Β͍Ͱे෼

    View Slide

  90. ElectronͰͲ͏͢Δ͔ʁ
    • λΠϜϥΠϯΛ͢΂ͯදࣔ͢ΔͷΛ΍ΊΔ
    • ࠷৽40݅ͷΈΛදࣔ͠ɼඞཁͰ͋Ε͹
    LazyLoading
    • StreamingͰߋ৽͞Εͨ৔߹͸ɼݹ͍΋ͷΛফ
    ͯ͠40݅ʹอͭ

    View Slide

  91. View Slide

  92. εΫϩʔϧΠϕϯτΛ΋ͱʹ੍ޚͯ͠΍Δ

    View Slide

  93. 200MBΛ੾Δʂ

    View Slide

  94. ѹ౗త͡Όͳ͍͔ʂ

    View Slide

  95. ϙΠϯτɿ
    Vue.jsͷύϑΥʔϚϯεʹ΋
    ؾΛ഑Δ

    View Slide

  96. vue.jsͷύϑΥʔϚϯε
    • v-ifͱv-show
    • v-if: ੾ସ࣌ʹhtml͕ੜ੒͞ΕϨϯμϦϯά͞
    ΕΔ
    • v-show: ͸͡Ί͔ΒϨϯμϦϯά͞Εͯ͸͍Δ
    ͕ɼdisplay: none͞Ε͍ͯΔ͚ͩ

    View Slide

  97. v-ifͱv-show
    • v-ifͷ੾ସ࣌ϨϯμϦϯάίετ͸അࣛʹͳΒ
    ͳ͍
    • ͔͠͠ɼඞཁͷͳ͍ͱ͜ΖΛv-showʹ͢Δͱ
    ͣͬͱϝϞϦΛফඅ͠ଓ͚Δ

    View Slide

  98. ͜͜͸ਖ਼ղ͕ͳ͍

    View Slide

  99. ࠷ۙͷWhalebird
    • ϝϞϦফඅ: 200MB ~ 500MB
    • 500MB͘Β͍·Ͱ͘ΔͱGC͞ΕͯϝϞϦফඅ
    ͕ҰؾʹݮΔ
    • ը૾͕গͳ͍࣌ؒଳ͸͍ܰʂ

    ʢpawooͷਓ͝ΊΜͳ͍͞

    View Slide

  100. ࠷ۙͷWhalebird
    • ϕʔεʹͳ͍ͬͯΔElectronΛόʔδϣϯΞο
    ϓ͢ΔͱϝϞϦফඅ͕ݮΔ
    • ύϑΥʔϚϯε͸Chromiumʹ߹ΘͤͯͲΜͲ
    Μྑ͘ͳΔ

    View Slide

  101. ͜ͷઌͷ࡞ઓ
    • ը૾ͷඇදࣔΦϓγϣϯ
    • τΡʔτ͕࿈ଓ͢Δ৔߹͸·ͱΊͯϨϯμϦ
    ϯάͰ͖ͳ͍͔ʁ

    View Slide

  102. ͓ӄ༷Ͱ࠷ۙͷ൓Ԡ͸ྑ͍

    View Slide

  103. APIΫϥΠΞϯτϥΠϒϥϦ
    Λࣗ࡞͢Δ

    View Slide

  104. ౰ॳ͸mastodon-apiͱ͍͏
    Node.jsͷϥΠϒϥϦΛར༻

    View Slide

  105. ͕ɼΤϥʔʹͳΔͱ͍͏ใࠂ
    ͕ͪΒ΄Β

    View Slide

  106. mastodon-api
    • POSTύϥϝʔλΛbodyͰ͸ͳ͘urlύϥϝʔ
    λͱͯ͠ૹ৴͍ͯ͠Δ
    • Ұ෦αʔόͰ͸ͦΕΒ͕ڋ൱͞Ε͍ͯΔ
    ଞͷબ୒ࢶ͕ͳ͍

    View Slide

  107. ͳ͍ͷͳΒࣗ࡞͠Α͏

    View Slide

  108. View Slide

  109. megalodon
    • TypeScriptͰॻ͍ͨmastodonAPIΫϥΠΞϯ
    τϥΠϒϥϦ
    • Streaming΋࣮૷ࡁΈ
    • OAuthΞϓϦέʔγϣϯొ࿥༻ϝιου΋༻
    ҙ

    View Slide

  110. public get(path: string, params = {}): Promise> {
    return axios
    .get(this.baseUrl + path, {
    headers: {
    'Authorization': `Bearer ${this.accessToken}`
    },
    params
    })
    .then((resp: AxiosResponse) => {
    const res: Response = {
    data: resp.data,
    status: resp.status,
    statusText: resp.statusText,
    headers: resp.headers
    }
    return res
    })
    }

    View Slide

  111. όάͬͯͨ৔߹͸
    શ෦ࣗ෼Ͱ࣏ͤΔ

    View Slide

  112. ΠϯελϯεΛ
    ݐͯΔ͜ͱ΋͋Δ

    View Slide

  113. ΠϯελϯεݪҼͷ໰͍߹Θͤ
    ͸ଟ͍
    • ϩάΠϯ͕Ͱ͖ͳ͍
    • τΡʔτͰ͖ͳ͍
    • Streaming͕ಈ͔ͳ͍
    • ౳ʑ……

    View Slide

  114. ࠷ۙ͋ͬͨ൵͍͠ࣄྫ
    • (mastodon͕࢖͍ͬͯΔ)doorkeeper 4.3.0Ҏ
    ্ Ͱnative_redirect_uriʹؔ͢Δόά͕ࠞೖ
    • mastodon: doorkeeper ~> 4.4.1
    • σεΫτοϓΞϓϦέʔγϣϯͰೝূ͕Ͱ͖
    ͳ͘ͳΔ

    View Slide

  115. ͔֬ΊΔ&ϓϧϦΫΛग़͢
    • खݩͰmastodonαʔόΛݐͯΔ: 

    https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/
    Development-guide.md
    • ࠶ݱͨ͠
    • doorkeeperʹissueཱͯͨΓɼmastodonʹϓ
    ϧϦΫΛૹͬͨΓ

    View Slide

  116. View Slide

  117. ΫϥΠΞϯτ͚ͩͷ໰୊Ͱ͸ͳ͍͜ͱ͕ଟ͍ͷͰɼ
    αΫοͱΠϯελϯεΛཱͯΒΕΔΑ͏ʹ
    ͓ͯ͘͠ͷॏཁ

    View Slide

  118. ·ͱΊ

    View Slide

  119. ੒ޭͨ͠ͳʔͱࢥ͏͜ͱ
    • ElectronͰ࡞ͬͨ͜ͱ
    • Vue.jsͱ͍͏બ୒
    • ӳޠݍ΁ͷ഑ྀ

    View Slide

  120. ࣦഊͨ͠ͳʔͱࢥ͏͜ͱ
    • ΋ͬͱૣ͘࡞Ε͹Α͔ͬͨ
    • ΋ͬͱૣ͘TypeScriptΛߟྀ͢΂͖ͩͬͨ
    • megalodon(APIΫϥΠΞϯτ)͸ϝϯς͠΍
    ͍͢
    • ద౰ͳΦϒδΣΫτΛ౉͢͜ͱ͕ଟ͍

    View Slide

  121. 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Ͱߦ͏
    ະ஌ͷΦϒδΣΫτ

    View Slide

  122. શମతʹݟͯ
    • Electron͸ʢϦϦʔεํ๏΋ؚΊͯʣਐԽͯ͠
    ͍ΔͷͰ͓͢͢Ί͍ͨ͠
    • ϝϞϦফඅ͸ରࡦՄೳ
    • Vue.jsͰGUIΞϓϦέʔγϣϯ։ൃ͢Δͷ͸ྑ
    ͍

    View Slide

  123. Mastodon͕
    շదʹͳͬͨͷͰ
    TwitterΛݟΔ͜ͱ͕ݮͬͨ

    View Slide

  124. ͞Α͏ͳΒTwitter
    ΫϥΠΞϯτ

    View Slide