electron: from beginner to pro
TRANSCRIPT
ELECTRON:BEGINNER TO PRO
BUILD CROSS PLATFORM DESKTOP APPS USINGGITHUB’S ELECTRON
@chrisgriffith
WHAT IS ELECTRON?Released in July 2013 by Cheng ZhaoFoundation for GitHub Atom Editor
ELECTRON'S FEATURES
Automatic updatesNative menus & notificationsCrash reportingDebugging & profilingWindows installersjust a partial list…
PLATFORM SUPPORT
HOW DOES ELECTRON WORK?
UI?
INSTALLING ELECTRONnpm install -g electron
QUICK STARTgit clone https://github.com/electron/electron-quick-start quick-start
cd quick-start
git init
npm start
DEFAULT FILE STRUTURE index.html LICENSE.md main.js package.json README.md renderer.js
REAL WORLD FILE STRUTURE � app main.js splash.html splash.png � www � build � dist � node_modules package-lock.json package.json
MAIN.JS const electron = require('electron') // Module to control application life. const app = electron.app // Module to create native browser window. const BrowserWindow = electron.BrowserWindow const path = require('path') const url = require('url')
let mainWindow
CREATEWINDOW function createWindow () { // Create the browser window. mainWindow = new BrowserWindow({width: 800, height: 600}) // and load the index.html of the app. mainWindow.loadURL(url.format({ pathname: path.join(__dirname, 'index.html'), protocol: 'file:', slashes: true })) …
CREATEWINDOW … // Open the DevTools. mainWindow.webContents.openDevTools()
// Emitted when the window is closed. mainWindow.on('closed', function () { // Dereference the window object, usually you would store windows // in an array if your app supports multi windows, this is the time // when you should delete the corresponding element. mainWindow = null }) }
MAIN.JS // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. app.on('ready', createWindow)
INDEX.HTML… <h1>Hello World!</h1> <!-- All of the Node.js APIs are available in this renderer process. --> We are using Node.js <script>document.write(process.versions.node) < /script>, Chromium <script>document.write(process.versions.chrome) < /script>, and Electron <script>document.write(process.versions.electron) < /script>. …
INDEX.HTML… <script> // You can also require other files to run in this process require('./renderer.js') < /script>
WINDOWS
BROWSERWINDOW mainWindow = new BrowserWindow({ show: false, backgroundColor: "#FFF", width: 800, height: 600, minWidth: 800, maxWidth: 1024, minHeight: 600, maxHeight: 768, resizable: true, movable: true })
BROWSERWINDOWADDTIONAL PROPERTIES
mainWindow = new BrowserWindow({ show: false, backgroundColor: "#FFF", width: 800, height: 600, minWidth: 800, maxWidth: 1024, minHeight: 600, maxHeight: 768, resizable: true, movable: true, alwaysOnTop: false, title: "Goodbye, Moon?" })
FRAMELESS WINDOWS mainWindow = new BrowserWindow({ show: false, backgroundColor: '#FFF', transparent: true, width: 800, height: 600, minWidth: 800, maxWidth: 1024, minHeight: 600, maxHeight: 768, resizable: true, movable: true, // frame: false, titleBarStyle: 'hidden' //hidden-inset // title: "Goodbye, Moon?", })
TRANSPARENT WINDOWS mainWindow = new BrowserWindow({ show: false, // backgroundColor: '#FFF', transparent: true, width: 800, height: 600, minWidth: 800, maxWidth: 1024, minHeight: 600, maxHeight: 768, resizable: true, movable: true, frame: false, transparent: true })
APPLICATION MENU
MENUS const Menu = electron.Menu
app.on('ready', function () { const menu = Menu.buildFromTemplate(template) Menu.setApplicationMenu(menu) createWindow() })
MENU TEMPLATES let template = [{ label: 'Menu 1', submenu: [{ label: 'Menu item 1' }] }, { label: 'Menu 2', submenu: [{ label: 'Another Menu item' }, { label: 'One More Menu Item' }] }]
MENU ACCELERATORS & ROLES let template = [{ label: 'Edit App', submenu: [{ label: 'Undo', accelerator: 'CmdOrCtrl+Z', role: 'undo' }, { label: 'Redo', accelerator: 'Shift+CmdOrCtrl+Z', role: 'redo' }, { type: 'separator' }, { ...
CONTEXTUAL MENUS
CONTEXTUAL MENU -RENDERER.JS
const { remote } = require('electron') const { Menu } = remote const myContextMenu = Menu.buildFromTemplate ([ { label: 'Cut', role: 'cut' }, { label: 'Copy', role: 'copy' }, { label: 'Paste', role: 'paste' }, { label: 'Select All', role: 'selectall' }, { type: 'separator' }, { label: 'Custom', click() { console.log('Custom Menu') } } ])
window.addEventListener('contextmenu', (event) => { event.preventDefault() myContextMenu.popup() })
INTER-PROCESSCOMMUNICATION
INTER-PROCESS COMMUNICATION
IPC SYNC const ipc = require('electron').ipcRenderer syncMsgBtn.addEventListener('click', function () { const reply = ipc.sendSync('synchronous-message', 'Mr. Watson, come here })
const ipc = electron.ipcMain ipc.on('synchronous-message', function (event, arg) { event.returnValue = 'I heard you!' })
IPC ASYNC const ipc = require('electron').ipcRenderer asyncMsgBtn.addEventListener('click', function () { ipc.send('asynchronous-message', ''That's one small step for man') }) ipc.on('asynchronous-reply', function (event, arg) { const message = `Asynchronous message reply: ${arg}` document.getElementById('asyncReply').innerHTML = message })
const ipc = electron.ipcMain ipc.on('asynchronous-message', function (event, arg) { if (arg === 'That’s one small step for man') { event.sender.send('asynchronous-reply', ', one giant leap for mankind. } })
NATIVE DIALOGS
DIALOG TYPESFile OpenFile SaveMessage BoxError Box
FILE OPEN const dialog = electron.dialog
ipc.on('open-directory-dialog', function (event) { dialog.showOpenDialog({ properties: ['openDirectory'] }, function (files) { if (files) event.sender.send('selectedItem, files) }) })
DIALOG PROPERTIESopenFileopenDirectorymultiSelectionscreateDirectoryshowHiddenFilespromptToCreate (Windows Only)
MESSAGE BOXES
MESSAGE BOX dialog.showMessageBox({ type: info, buttons: ['Save', 'Cancel', 'Don\'t Save'], defaultId: 0, cancelId: 1, title: 'Save Score', message: 'Backup your score file?', detail: 'Message detail' })
DIALOG TYPESinfoerrorquestionnone
CUSTOM ICONS const nativeImage = electron.nativeImage
let warningIcon= nativeImage.createFromPath('images/warning.png')
dialog.showMessageBox({ type: info, buttons: ['Save', 'Cancel', 'Don\'t Save'], defaultId: 0, cancelId: 1, title: 'Save Score', message: 'Backup your score file?', detail: 'Message detail', icon: warningIcon })
WEBCONTENTS EVENTSbefore-input-eventcertificate-errorcontext-menucrashedcursor-changeddestroyeddevtools-closeddevtools-focuseddevtools-openeddevtools-reload-pagedid-change-theme-colordid-fail-loaddid-finish-loaddid-frame-finish-loaddid-get-response-detailsdid-get-redirect-requestdid-navigatedid-navigate-in-page
did-start-loadingdid-stop-loadingdom-readyfound-in-pageloginmedia-started-playingmedia-pausednew-windowpage-favicon-updatedpaintplugin-crashedselect-client-certificateselect-bluetooth-deviceupdate-target-urlwill-attach-webviewwill-navigatewill-prevent-unload
DEBUGGING YOUR ELECTRONAPPLICATION
Chromium’s Dev Tools
DEBUGGING RENDERERPROCESS
Chromium’s Dev Tools
DEBUGGING MAIN PROCESSVS Code's Toolsnode-inspector
DEVTRONAn Electron DevTools extension to help you inspect,
monitor, and debug your app.
TESTING WITH SPECTRON
INSTALLATION npm install --save-dev spectron
TEST SCRIPT npm install electron-builder --save-dev
BUILDING YOUR APPLICATION
INSTALLATION npm install electron-builder --save-dev
ADJUSTING YOUR BUILD DIRECTORIES
Build Platforms Descriptions--mac, -m, -o, --macos Build for macOS--win, -w, --windows Build for Windows--linux, -l Build for LinuxBuild Architectures Descriptions--x64 Build for x64--ia32 Build for ia32
UPDATING THE PACKAGE.JSONFILE
"scripts": { "start": "electron .", "dist": "build -mwl --x64 --ia32" }
UPDATING THE PACKAGE.JSONFILE
"build": { "appId": "com.your-company.electron-app-name", "copyright": "Copyright © 2017 YOUR-NAME", "productName": "My Electron App", "electronVersion": "1.4.1", "mac": { "category": "public.app-category.developer-tools" }, "win": { "target": [ "nsis" ] }, "linux": { "target": [ "AppImage", "deb"] } }
UPDATING THE PACKAGE.JSONFILE
"main": "./app/main.js"
APP ICONS16px32px128px256px (OS X 10.5+)512px (OS X 10.5+)1024px (OS X 10.7+)
CONFIGURING THE MACOS DMG
CONFIGURING THE WINDOWS INSTALLER
AUTO-UPDATING
BUILT-INPlatform Update MethodmacOS Squirrel.MacWindows SquirrelLinux None
ELECTRON-UPDATERInstall electron-updater as an app dependency.
Use autoUpdater from electron-updater instead ofelectron
npm i electron-updater
import { autoUpdater } from "electron-updater"
UPDATE EVENTS autoUpdater.on('checking-for-update', () => { })
autoUpdater.on('update-available', () => { })
autoUpdater.on('update-not-available', () => {})
autoUpdater.on('update-downloaded', () => {})
autoUpdater.on('error', (event, error) => {})
ELECTRON FORGEA complete tool for building modern Electron
applications.
https://github.com/electron-userland/electron-forge
THANK YOU!Chris Griffith
San Diego, CA
@chrisgriffith
http://chrisgriffith.wordpress.com
https://github.com/chrisgriffith