├── .editorconfig
├── .gitattributes
├── .gitignore
├── background
├── index.html
└── index.js
├── index.js
├── license
├── package.json
├── readme.md
├── renderer
├── index.css
├── index.html
└── index.js
└── shared
└── task.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = tab
5 | end_of_line = lf
6 | charset = utf-8
7 | trim_trailing_whitespace = true
8 | insert_final_newline = true
9 |
10 | [{package.json,*.yml}]
11 | indent_style = space
12 | indent_size = 2
13 |
14 | [*.md]
15 | trim_trailing_whitespace = false
16 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | /dist
3 |
--------------------------------------------------------------------------------
/background/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/background/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | const { ipcRenderer } = require('electron');
3 | const task = require('../shared/task');
4 |
5 | window.onload = function () {
6 | ipcRenderer.on('background-start', (startTime) => {
7 | ipcRenderer.send('background-response', {
8 | result: task(),
9 | startTime: startTime
10 | });
11 | });
12 | };
13 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | const { app, BrowserWindow, ipcMain } = require('electron');
3 |
4 | // prevent window being garbage collected
5 | let mainWindow;
6 | let backgroundWindow;
7 |
8 | function onClosed() {
9 | // dereference the window
10 | // for multiple windows store them in an array
11 | mainWindow = null;
12 | backgroundWindow = null;
13 | }
14 |
15 | function createMainWindow() {
16 | const win = new BrowserWindow({
17 | width: 800,
18 | height: 600
19 | });
20 |
21 | win.loadURL(`file://${__dirname}/renderer/index.html`);
22 | win.on('closed', onClosed);
23 |
24 | return win;
25 | }
26 |
27 | function createBackgroundWindow() {
28 | const win = new BrowserWindow({
29 | show: false
30 | });
31 |
32 | win.loadURL(`file://${__dirname}/background/index.html`);
33 |
34 | return win;
35 | }
36 |
37 | app.on('window-all-closed', () => {
38 | if (process.platform !== 'darwin') {
39 | app.quit();
40 | }
41 | });
42 |
43 | app.on('activate-with-no-open-windows', () => {
44 | if (!mainWindow) {
45 | mainWindow = createMainWindow();
46 | }
47 | });
48 |
49 | app.on('ready', () => {
50 | mainWindow = createMainWindow();
51 | backgroundWindow = createBackgroundWindow();
52 | });
53 |
54 | ipcMain.on('background-response', (event, payload) => mainWindow.webContents.send('background-response', payload));
55 |
56 | ipcMain.on('background-start', (event, payload) => backgroundWindow.webContents.send('background-start', payload));
57 |
--------------------------------------------------------------------------------
/license:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) John Haley (http://johnhaley.io)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "electron-background-task-app",
3 | "productName": "electron-background-task-app",
4 | "version": "0.0.0",
5 | "description": "Shows off how to run a task in the background",
6 | "license": "MIT",
7 | "repository": "johnhaley81/electron-background-task-app",
8 | "author": {
9 | "name": "John Haley",
10 | "email": "john@haley.io",
11 | "url": "johnhaley.io"
12 | },
13 | "engines": {
14 | "node": ">=4"
15 | },
16 | "electronVersion": "1.0.1",
17 | "scripts": {
18 | "test": "xo",
19 | "start": "electron .",
20 | "build": "electron-packager . $npm_package_productName --out=dist --ignore='^/dist$' --prune --asar --all --version=$npm_package_electronVersion"
21 | },
22 | "files": [
23 | "index.js",
24 | "index.html",
25 | "index.css"
26 | ],
27 | "keywords": [
28 | "electron-app"
29 | ],
30 | "dependencies": {
31 | "electron-debug": "^0.3.0"
32 | },
33 | "devDependencies": {
34 | "electron-packager": "^5.0.0",
35 | "electron-prebuilt": "1.0.1",
36 | "spectron": "^3.0.0",
37 | "xo": "^0.10.0"
38 | },
39 | "xo": {
40 | "esnext": true,
41 | "envs": [
42 | "node",
43 | "browser"
44 | ]
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # electron-background-task-app
2 |
3 | > This app shows off how to run a task in the background of an electron app.
4 |
5 |
6 | ## Dev
7 |
8 | ```
9 | $ npm install
10 | ```
11 |
12 | ### Run
13 |
14 | ```
15 | $ npm start
16 | ```
17 |
18 | ### Build
19 |
20 | ```
21 | $ npm run build
22 | ```
23 |
24 | Builds the app for OS X, Linux, and Windows, using [electron-packager](https://github.com/maxogden/electron-packager).
25 |
26 |
27 | ## License
28 |
29 | MIT © [John Haley](http://johnhaley.io)
30 |
--------------------------------------------------------------------------------
/renderer/index.css:
--------------------------------------------------------------------------------
1 | html,
2 | body {
3 | padding: 0;
4 | margin: 0;
5 | }
6 |
7 | body {
8 | font-family: -apple-system, 'Helvetica Neue', Helvetica, sans-serif;
9 | }
10 |
11 | header {
12 | position: absolute;
13 | width: 500px;
14 | height: 250px;
15 | top: 50%;
16 | left: 50%;
17 | margin-top: -225px;
18 | margin-left: -250px;
19 | text-align: center;
20 | }
21 |
22 | header h1 {
23 | font-size: 60px;
24 | font-weight: 100;
25 | margin: 0;
26 | padding: 0;
27 | }
28 |
29 | header div {
30 | margin: 20px;
31 | font-size: 15px;
32 | }
33 |
34 | a {
35 | box-shadow:inset 0px 1px 0px 0px #ffffff;
36 | background:linear-gradient(to bottom, #ffffff 5%, #f6f6f6 100%);
37 | border-radius:6px;
38 | border:1px solid #dcdcdc;
39 | display:inline-block;
40 | cursor:pointer;
41 | color:#666666;
42 | font-family: -apple-system, 'Helvetica Neue', Helvetica, sans-serif;;
43 | font-size:15px;
44 | font-weight:bold;
45 | padding:6px 24px;
46 | text-decoration:none;
47 | text-shadow:0px 1px 0px #ffffff;
48 | }
49 | a:hover {
50 | background:linear-gradient(to bottom, #f6f6f6 5%, #ffffff 100%);
51 | }
52 | a:active {
53 | position:relative;
54 | top:1px;
55 | }
56 |
--------------------------------------------------------------------------------
/renderer/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Electron background task runner
6 |
7 |
8 |
9 |
10 |
11 |
12 | Lets run some long running task and watch what it does to the UI
13 |
20 |
21 | Waiting...
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/renderer/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | const { ipcRenderer } = require('electron');
3 | const task = require('../shared/task');
4 |
5 | window.onload = function () {
6 | setInterval(() => {
7 | const progressBar = document.getElementById('progress-bar');
8 | const maxValue = parseInt(progressBar.getAttribute('max'), 10);
9 | let nextValue = parseInt(progressBar.getAttribute('value'), 10) + 1;
10 |
11 | if (nextValue > maxValue) {
12 | nextValue = 0;
13 | }
14 |
15 | progressBar.setAttribute('value', nextValue);
16 | }, 25);
17 |
18 | function startProcess() {
19 | document.getElementById('status').textContent = 'Started!';
20 | }
21 |
22 | function finishProcess(result, timeElapsed) {
23 | document.getElementById('status').textContent =
24 | 'Finished with a result of: ' +
25 | result +
26 | ' in ' +
27 | (timeElapsed / 1000) +
28 | ' seconds';
29 | }
30 |
31 | const rendererButton = document.getElementById('in-renderer');
32 |
33 | rendererButton.onclick = function longRunningRendererTask() {
34 | const startTime = new Date();
35 |
36 | // Note that the UI won't update with this call since we're stuck in a JavaScript process and the UI is
37 | // unresponsive until this loop finishes. The div will go straight to finished.
38 | startProcess();
39 |
40 | finishProcess(task(), new Date() - startTime);
41 | };
42 |
43 | const backgroundButton = document.getElementById('in-background');
44 |
45 | backgroundButton.onclick = function longRunningBackgroundTask() {
46 | // We have to cast to a number because crossing the IPC boundary will convert the Date object to an empty object.
47 | // Error, Date and native objects won't be able to be passed around via IPC.
48 | const backgroundStartTime = +new Date();
49 |
50 | startProcess();
51 | ipcRenderer.send('background-start', backgroundStartTime);
52 | }
53 |
54 | ipcRenderer.on('background-response', (event, payload) => {
55 | finishProcess(payload.result, new Date() - payload.startTime);
56 | });
57 | };
58 |
--------------------------------------------------------------------------------
/shared/task.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // This module is instantiated twice. Once in the background process and once in the renderer process. They can't
4 | // share data other than through IPC.
5 |
6 | module.exports = function task() {
7 | let result = 0;
8 |
9 | for (let i = 0; i < 100000000; i++) {
10 | result += i;
11 | }
12 |
13 | return result;
14 | };
15 |
--------------------------------------------------------------------------------