Slide 1

Slide 1 text

Electron × React લ୺։ᚙऀߴ଎ލք䖂໘։ᚙ Shao-Chung Chen @ ReactJS.tw Meetup #8 Courtesy: 2d75.deviantart.com

Slide 2

Slide 2 text

Full-Stack Web Developer LinkedIn.com/in/dannvix GitHub.com/dannvix

Slide 3

Slide 3 text

ຊ೔ Demo ༻ Apps https://github.com/dannvix/Electron-React-Demo-Apps

Slide 4

Slide 4 text

‣ Electron֓᧺ ‣ ୈҰݸElectron × React App ‣ Electronመፌٕ޼ ‣ Electronআࡨᢛଌࢼ ‣ ElectronҰࠣ໰୊

Slide 5

Slide 5 text

ҎWebٕज़։ᚙ䖂໘ೈᱪੋॄኄ֓೦ʁ ‣ WebView, QtWebKit, React Native (?), Chrome Apps (Packaged Apps), ... ‣ Electron֓᧺ ‣ ୈҰݸElectron × React App ‣ Electronመፌٕ޼ ‣ Electronআࡨᢛଌࢼ ‣ ElectronҰࠣ໰୊

Slide 6

Slide 6 text

ഝੋ໢ทᖣ᧸ثɼେՈ኷ख़ࣩ Courtesy: Subtle Patterns

Slide 7

Slide 7 text

ഝੋElectron App Courtesy: Subtle Patterns

Slide 8

Slide 8 text

ॴҎElectronੋॄኄʁ ‣ ؆ᄸိ㘸ɼबੋҎio.jsૢ࡞తChromiumᖣ᧸ث

Slide 9

Slide 9 text

ഝੋਅతElectron App Courtesy: Subtle Patterns

Slide 10

Slide 10 text

Կ࣌࢖༻Electronʁ ‣ շ଎䖂໘։ᚙɺޯᯮሢҊ਽ܗ ‣ ఔࣜԽૢ࡞Chromium ‣ ላशChromium Content API

Slide 11

Slide 11 text

૬ֱReact Native༗Կෆಉ೭႔ʁ ‣ React Nativeੋ༻JavaScript APIૢ࡞Native UIݩ݅ ‣ React Nativeᔒ༗CSS ‣ Ҿᰍظ㨙React Native for Desktopʁ

Slide 12

Slide 12 text

Electron࢖༻መྫ ‣ Courtesy: http://electron.atom.io ? ౳㟬ိ։ᚙʂ

Slide 13

Slide 13 text

ஶखݐཱୈҰݸElectron × React App ‣ ኺྵ։࢝ɼ୞ཁࡾݸ䈕Ҋɼ኷؆ᄸతʂ ‣ Electronจ݅े෼ᴡશʂ ‣ Electron֓᧺ ‣ ୈҰݸElectron × React App ‣ Electronመፌٕ޼ ‣ Electronআࡨᢛଌࢼ ‣ ElectronҰࠣ໰୊

Slide 14

Slide 14 text

Electron App ሢҊՍߏ your-­‐app/  │  ├──  package.json  ├──  main.js  └──  index.html  package.json {    "name"        :  "your-­‐app",    "version"  :  "0.1.0",    "main"        :  "main.js" }  main.js var  app  =  require("app"),        BrowserWindow  =  require("browser-­‐window"); var  mainWindow  =  null;  //anti-­‐GC app.on("ready",  function()  {        mainWindow  =  new  BrowserWindow({...});        mainWindow.loadUrl("file://"+__dirname+"index.html");        ... });  index.html    Hello  world!    ...

Slide 15

Slide 15 text

Chromiumଟߦఔ Multi-Process Սߏ ‣ http://dev.chromium.org/developers/design-documents/multi-process-architecture ᖣ᧸ثओߦఔ ߇੍ثɼҎC++ฤሜ ࢹᜬ ࢹᜬ ࢹᜬ  Tray બᄸ ሣ࿩ᐽ ߦఔؒ௨ਜػ੍ IPC, Inter-Process Communication ࢉ៸ߦఔ Renderer WebKit DOM API ࢉ៸ߦఔ Renderer WebKit DOM API ࢉ៸ߦఔ Renderer WebKit DOM API

Slide 16

Slide 16 text

Electronଟߦఔ Multi-Process Սߏ ‣ https://github.com/atom/electron/blob/master/docs/tutorial/quick-start.md Electronओߦఔ ߇੍ثɼҎC++ฤሜɼఏڙJavaScript API ࢹᜬ ࢹᜬ ࢹᜬ  Tray બᄸ ሣ࿩ᐽ ߦఔؒ௨ਜػ੍ IPC, Inter-Process Communication WebKit DOM API Node.js API WebKit DOM API Node.js API WebKit DOM API Node.js API main.js index.html app.react.js ࢉ៸ߦఔ Renderer ࢉ៸ߦఔ Renderer ࢉ៸ߦఔ Renderer

Slide 17

Slide 17 text

؆Խိ㘸ɼՄࢹҝຊ஍୺Server–Client֓೦ ‣ ၷ୺౎Մ༻requireҾೖpackages ‣ ॴ༗GUI૬᮫؅ཧɺૢ࡞౎ඞਢࡏओߦఔ main process ׬੒ ‣ Electronతࢉ៸ߦఔ renderer process ൺىҰൠᖣ᧸ث༗ߋߴᒟݶ ‣ ࢉ៸ߦఔతJavaScript؀ڥҝwindowᢛglobalڞଘɼ ҙଈtop this = window = global Electronओߦఔ ߇੍ث ࢹᜬ  *1$31$ WebKit DOM API Node.js API main.js app.js ࢉ៸ߦఔ Renderer

Slide 18

Slide 18 text

ߦఔؒ௨ਜػ੍ IPC ᢛ RPC Electronओߦఔ ߇੍ث ࢹᜬ  *1$31$ WebKit DOM API Node.js API main.js app.js ‣ https://www.chromium.org/developers/design-documents/inter-process-communication  main.js var  app  =  require("app"),        ipc  =  require("ipc"); app.on("ready",  function()  {    ...    ipc.on("do-­‐job",  function(evt,  args)  {        ...        //  evt.sender:  source  WebContents        evt.sender.send("reply-­‐data",  {                jobId:  "123",                data:  [...]        });    }); });  app.js var  remote  =  require("remote"),        ipc  =  require("ipc"); //  RPC remote.getCurrentWindow().toggleDevTools(); //  IPC ipc.send("do-­‐job",  {    jobId:  "123" }); ipc.on("reply-­‐data",  function(args)  {    console.log(args.type);    console.log(args.data.join(",")); }); ‣ ݺڣRPCհ໘ remote ࣌ඞਢཹҙremote bufferతserialization ໰୊ ‣ ৄhttps://github.com/atom/electron/blob/master/docs/api/remote.md ࢉ៸ߦఔ Renderer ‣ ࡏWIndowsੋ༻Named Pipes ࡏOS X࿨Linux࢖༻Domain Sockets ‣ chromium/src/ipc/ipc_channel.h chromium/src/ipc/ipc_channel_win.cc chromium/src/ipc/ipc_channel_posix.cc

Slide 19

Slide 19 text

ڧྗ૊߹ React × React-Router × Alt ‣ Single-Page Application (SPA)

Slide 20

Slide 20 text

ލBrowserWindowత㐫ଶڞڗ ‣ धಁաremote҃ipcɼҎmain.jsҝڮྊਐߦኍ೻ ‣ ໨લෆ֬ఆݪੜAltೳ൱၏౸ ‣ ჩߟhttps://speakerdeck.com/misumirize/being-flux-on-electron ‣ एੋwindow.open()։啟తBrowserWindow ೗settings ຠՄಁաpostMessage()൴ࠑަ׵ਜଉ ‣ ჩߟhttps://github.com/atom/electron/blob/master/docs/api/window-open.md ೗Flux໛ܕதతAction Dispatch ࢹᜬ" ࢹᜬ$ ओߦఔ ࢹᜬ# postMessage ipc ipc ipc

Slide 21

Slide 21 text

“Kitematic” — Docker GUI for OS X ‣ ༏ྑElectron × React × React-Router × Alt × Grunt × Babelჩߟመ࡞ʂ Courtesy: Subtle Patterns

Slide 22

Slide 22 text

Electron መፌٕ޼ ‣ Electron֓᧺ ‣ ୈҰݸElectron × React App ‣ Electronመፌٕ޼ ‣ Electronআࡨᢛଌࢼ ‣ ElectronҰࠣ໰୊

Slide 23

Slide 23 text

ແᬑᐽࢹᜬ  main.js var  app  =  require("app"),        BrowswerWindow  =  require("browser-­‐window"); mainWindow  =  null; app.on("ready",  function()  {    mainWindow  =  new  BrowserWindow({        ...        resizable:  true,        frame:  false,        transparent:  false,        ...    });    ... });  style.css html,  body  {    width:  100%;    height:  100%;    -­‐webkit-­‐user-­‐select:  none;    -­‐webkit-­‐app-­‐region:  drag; } button  {    -­‐webkit-­‐app-­‐region:  no-­‐drag;  //  must-­‐have } ‣ https://github.com/atom/electron/blob/master/docs/api/frameless-window.md

Slide 24

Slide 24 text

ಁ໌ࢹᜬ  main.js var  app  =  require("app"),        BrowswerWindow  =  require("browser-­‐window"); //  Chromium  command-­‐line  switches  for  Linux app.commandLine.appendSwitch("enable-­‐transparent-­‐visuals",  1); app.commandLine.appendSwitch("disable-­‐gpu",  1); mainWindow  =  null; app.on("ready",  function()  {    mainWindow  =  new  BrowserWindow({        ...        resizable:  false,        frame:  false,        transparent:  true,        ...    });    ... });  style.css html,  body  {    ...    background:  transparent; } ‣ https://github.com/atom/electron/blob/master/docs/api/frameless-window.md ‣ ׈૏ᴍ㐝ಁ໌႔ฒෆ။ઠաࢹᜬ ‣ ಁ໌ࢹᜬෆՄվᏓେখ resizable:  false ‣ Windowsඞਢ啟ಈDWM ଈAeroध啟༻ ‣ LinuxඞਢၷݸՃ্Chromiumత໋ྩྻჩᏐ

Slide 25

Slide 25 text

બᄸྻ menu ‣ https://github.com/atom/electron/blob/master/docs/api/menu.md ‣ https://github.com/atom/electron/blob/master/docs/api/menu-item.md

Slide 26

Slide 26 text

ܥ౷ྻᅷࣔ tray ‣ https://github.com/atom/electron/blob/master/docs/api/tray.md શҬշ଎ݤ global-­‐shortcut ‣ https://github.com/atom/electron/blob/master/docs/api/global-shortcut.md ‣ શҬɼॴҎᔒ༗focusࡏElectron Appࢹᜬ໵။༗൓ጯ ‣ ࡏOS XɺWindowsᢛLinuxۉద༻ ‣ ར༻ࣈ۲ ೗Ctrl+X දࣔ҈ݤ૊߹ɼލฏ୆త҈ݤधࣗߦ႔ཧ ‣ ಛघ҈ݤෆ֬ఆࢧԉఔ౓9%

Slide 27

Slide 27 text

ሣ࿩ᐽ dialog ‣ https://github.com/atom/electron/blob/master/docs/api/dialog.md ‣ ແ๏औಘ䈕Ҋ׬੔࿏ኸ ‣ ElectronఏڙNativeਜଉࢹᜬᢛ䈕Ҋᖣ᧸ࢹᜬ  app.js var  remote  =  require("remote"),        dialog  =  remote.require("dialog"); dialog.showSaveDialog(    remote.getCurrentWindow(),    {        title:  "Export  to  PDF",        filters:  [{              name:  "PDF  Documents",              extensions:  ["pdf"]        }]    },    function(pathname)  {        if  (!pathname)  return;        ipc.send("export-­‐to-­‐pdf",  {            pathname:  pathname        });    } ); ‣ ৄݟchromium/src/third_party/WebKit/Source/core/html/forms/FileInputType.cppதFileInputType::getTypeSpecificValue()

Slide 28

Slide 28 text

䈕Ҋ䇪Ӫ Drag & Drop ‣ https://github.com/atom/electron/blob/master/docs/api/file-object.md ‣ ఏڙe.dataTransfer.files[0].pathՄҎ௚઀ଘऔ䈕Ҋ׬੔࿏ኸ  app.js var  holder  =  document.getElementById("file-­‐holder"); holder.ondragover  = holder.ondragend  = holder.ondragleave  =  function()  {    return  false; }; holder.ondrop  =  function(e)  {    e.preventDefault();    var  file  =  e.dataTransfer.files[0];    console.log("Full  pathname:  "  +  file.path);    return  false; };

Slide 29

Slide 29 text

ᅷจॖ์ Zoom ‣ https://github.com/atom/electron/blob/master/docs/api/web-frame.md  app.js (function  enableZoomingHotKeysAndMouseWheel()  {    var  webFrame  =  require("web-­‐frame"),            currentZoomFactor  =  1.0;    window.addEventListener("keyup",  function(e)  {        if  (e.ctrlKey)  {            switch  (e.keyCode)  {            case  187/*=*/:                currentZoomFactor  +=  0.1;                break;            case  189/*-­‐*/:                currentZoomFactor  -­‐=  0.1;                break;            case    48/*0*/:                currentZoomFactor  =  1.0;                break;            };            webFrame.setZoomFactor(currentZoomFactor);        }    },  false);    window.addEventListener("mousewheel",  function(e)  {        if  (e.ctrlKey)  {            currentZoomFactor  +=  (e.wheelDelta  >  0)  ?  (0.1)  :  (-­‐0.1);            webFrame.setZoomFactor(currentZoomFactor);        }    },  false); })(); ‣ Electronࣅݷᔒ༗㚎ݐ೤ݤ࿨ᕵྠॖ์ ‣ ᔒ᮫܎ɼզ၇ՄҎ༻eventࣗݾ၏ ‣ Electron v0.28.3༗ࢧԉPinchॖ์

Slide 30

Slide 30 text

༌ग़PNGᢛPDF ‣ https://github.com/atom/electron/blob/master/docs/api/browser-window.md ‣ https://github.com/atom/electron/blob/master/docs/api/remote.md  main.js ipc.on("export-­‐pdf",  function(evt,  args)  {    var  pathname  =  args.pathname  ||  "/tmp/output.pdf";    mainWindow.printToPDF({            //  ref.  electron/atom/browser/api/lib/web-­‐contents.coffee        },        function(error,  pdfBuffer)  {            if  (error)  throw  error;            require("fs").writeFile(pathname,  pdfBuffer);        }    ); }); ‣ Electron࠷৽ᬶग़൛ຊ v0.28.2 ࠽੔ซprintToPDF() ‣ 㣿ᅷ୞ೳ፛ՄࢹეҬɼधࣗߦҎ㣥઀ ‣ ሱԙ(6*ૢ࡞ɼ୞ೳࡏओߦఔ main process ׬੒ʀ ࡏࢉ៸ߦఔ renderer process ՄಁաRPC࢖༻  app.js var  remote  =  require("remote"),        currentWindow  =  remote.getCurrentWindow(); currentWindow.capturePage({/*x,y,w,h*/},  function(buf)  {    //  serialize  remote  buffer  using  base64  data  url    var  dataUrl  =  buf.toDataUrl();    var  buffer  =  new  Buffer(        dataUrl.replace(/^data:image\/\w+;base64,/,  ""),  "base64");    require("fs").writeFile("/tmp/output.png",  buffer); });

Slide 31

Slide 31 text

ҎElectron-Packagerଧแ ‣ https://github.com/maxogden/electron-packager ‣ ࣗಈ׬੒Լࡌelectron-­‐prebuiltᢛൖ䈕Ҋ ‣ ڠॿߋ׵ࣥߦ䈕໊᜝ᢛᅷࣔ ‣ OS X။ଧแҝYour-­‐App.appࢿྉᇄ ‣ LinuxᢛWindows໨લနແ๏ଧแ੒ᄸҰࣥߦ䈕  pack.bat rmdir  Your-­‐App-­‐win32  /S  /Q electron-­‐packager  .  Your-­‐App  -­‐-­‐platform=win32  -­‐-­‐arch=x64  -­‐-­‐version=0.28.2  ^    -­‐-­‐ignore="\.git"  ^    -­‐-­‐ignore="node_modules\\electron-­‐prebuilt"  ^    -­‐-­‐ignore="node_modules\\electron-­‐packager"  ^    -­‐-­‐ignore=".*\.csv"

Slide 32

Slide 32 text

ElectronແݶՄೳɼ౳㟬ိᚙ۷ʂ ‣ ໨લ୞ࢧԉOS Xతࣗಈߋ৽ auto-­‐updater https://github.com/atom/electron/blob/master/docs/api/auto-updater.md ‣ Ⴉష฽ clipboard https://github.com/atom/electron/blob/master/docs/api/clipboard.md ‣ ؂ࢹిݯ㐫ଶ power-­‐monitor https://github.com/atom/electron/blob/master/docs/api/power-monitor.md ‣ ࣗఆڠఆ໊᜝ protocol https://github.com/atom/electron/blob/master/docs/api/protocol.md ‣ ᦊນჩᏐᢛଟᦊນࢧԉ screen https://github.com/atom/electron/blob/master/docs/api/screen.md

Slide 33

Slide 33 text

Electron আࡨᢛଌࢼ ‣ ࢧԉSelenium × WebDriverJS × ChromeDriver૊߹ IUUQTHJUIVCDPNBUPNFMFDUSPOCMPCNBTUFSEPDTUVUPSJBMVTJOHTFMFOJVNBOEXFCESJWFSNE ‣ ࢖༻धฤᩄతNative Node.js౟݅ https://github.com/atom/electron/blob/master/docs/tutorial/using-native-node-modules.md ‣ ᚙૹCrashใࠂ crash-­‐reporter https://github.com/atom/electron/blob/master/docs/api/crash-reporter.md ‣ Electron֓᧺ ‣ ୈҰݸElectron × React App ‣ Electronመፌٕ޼ ‣ Electronআࡨᢛଌࢼ ‣ ElectronҰࠣ໰୊

Slide 34

Slide 34 text

Electron Ұࠣ໰୊ ‣ Electron֓᧺ ‣ ୈҰݸElectron × React App ‣ Electronመፌٕ޼ ‣ Electronআࡨᢛଌࢼ ‣ ElectronҰࠣ໰୊ ‣ Electron Appଧแ೭ޙ໿ུधཁ100MB ‣ ແ๏ଧแҝᄸҰࣥߦ䈕 ‣ ໨લແ๏࢖༻React DevTools Extension ‣ ʜ

Slide 35

Slide 35 text

Fin.

Slide 36

Slide 36 text

\ຊท೭ޙੋิॆࢿਜ^

Slide 37

Slide 37 text

Chromium Content Module ‣ Courtesy: https://www.chromium.org/developers/content-module

Slide 38

Slide 38 text

No content