├── .gitignore ├── images ├── hello_world.png └── vscode_debugger.png ├── .vscode ├── tasks.json └── launch.json ├── app ├── renderer │ ├── styles │ │ ├── Headline.scss │ │ ├── colors.scss │ │ └── Main.scss │ ├── public │ │ ├── images │ │ │ └── GitHub-Mark-32px.png │ │ └── index.html │ ├── entry.jsx │ └── components │ │ ├── Headline.jsx │ │ └── Main.jsx └── main │ └── main.js ├── .eslintrc ├── package.json ├── README.md └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | build 4 | .idea -------------------------------------------------------------------------------- /images/hello_world.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogleasonjr/electron-react-webpack-quick-start/HEAD/images/hello_world.png -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "command": "npm", 4 | "isShellCommand": true, 5 | "args": [ "run", "build" ] 6 | } -------------------------------------------------------------------------------- /app/renderer/styles/Headline.scss: -------------------------------------------------------------------------------- 1 | @import 'colors'; 2 | 3 | .Headline-label { 4 | color: $heart-red; 5 | font-weight: bold; 6 | } -------------------------------------------------------------------------------- /images/vscode_debugger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogleasonjr/electron-react-webpack-quick-start/HEAD/images/vscode_debugger.png -------------------------------------------------------------------------------- /app/renderer/public/images/GitHub-Mark-32px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jogleasonjr/electron-react-webpack-quick-start/HEAD/app/renderer/public/images/GitHub-Mark-32px.png -------------------------------------------------------------------------------- /app/renderer/styles/colors.scss: -------------------------------------------------------------------------------- 1 | $heart-red: #d20c37; 2 | 3 | // Best to not use total white in any design. 4 | $white: #f5f5f5; 5 | // Best to not use total black in any design. 6 | $black: #121212; -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOptions": { 3 | "ecmaVersion": 6, 4 | "sourceType": "module", 5 | "ecmaFeatures": { 6 | "jsx": true 7 | } 8 | }, 9 | "rules": { 10 | "semi": 1 11 | } 12 | } -------------------------------------------------------------------------------- /app/renderer/entry.jsx: -------------------------------------------------------------------------------- 1 | // Need both React and ReactDOM for the JSX transpiler. 2 | import ReactDOM from 'react-dom'; 3 | import React from 'react'; 4 | 5 | import Main from './components/Main'; 6 | 7 | ReactDOM.render( 8 |
, 9 | document.getElementById('react-root') 10 | ); -------------------------------------------------------------------------------- /app/renderer/components/Headline.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './../styles/Headline.scss'; 3 | 4 | export default class Headline extends React.Component { 5 | render() { 6 | const text = 'React'; 7 | return {text}; 8 | } 9 | } -------------------------------------------------------------------------------- /app/renderer/styles/Main.scss: -------------------------------------------------------------------------------- 1 | @import 'colors'; 2 | 3 | .container { 4 | display: flex; 5 | flex-direction: column; 6 | align-items: center; 7 | justify-content: center; 8 | 9 | font-family: sans-serif; 10 | color: $black; 11 | } 12 | 13 | body { 14 | background: $white; 15 | } -------------------------------------------------------------------------------- /app/renderer/components/Main.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './../styles/Main.scss'; 3 | import Headline from './Headline'; 4 | 5 | export default class Main extends React.Component { 6 | render() { 7 | return (
8 |

Hello World

9 |

We are using node {process.versions.node}

10 |

Chrome {process.versions.chrome}

11 |

Electron {process.versions.electron}

12 |

and .

13 |
14 | ); 15 | } 16 | } -------------------------------------------------------------------------------- /app/renderer/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Hello World ❤ Electron, React, & Webpack 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch OSX", 6 | "type": "node", 7 | "request": "launch", 8 | "program": "${workspaceRoot}/build/main.bundle.js", 9 | "stopOnEntry": false, 10 | "args": [], 11 | "cwd": "${workspaceRoot}", 12 | "runtimeExecutable": "${workspaceRoot}/node_modules/electron-prebuilt/dist/Electron.app/Contents/MacOS/Electron", 13 | "runtimeArgs": [], 14 | "env": {}, 15 | "sourceMaps": true, 16 | "protocol": "legacy" 17 | }, 18 | { 19 | "name": "Launch Windows", 20 | "type": "node", 21 | "request": "launch", 22 | "program": "${workspaceRoot}/build/main.bundle.js", 23 | "stopOnEntry": false, 24 | "args": [], 25 | "cwd": "${workspaceRoot}", 26 | "runtimeExecutable": "${workspaceRoot}/node_modules/electron-prebuilt/dist/electron.exe", 27 | "runtimeArgs": [], 28 | "env": {}, 29 | "sourceMaps": true, 30 | "protocol": "legacy" 31 | } 32 | ] 33 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electron-react-webpack-quick-start", 3 | "version": "0.0.2", 4 | "description": "A minimal Electron application with React and Webpack", 5 | "main": "main.js", 6 | "scripts": { 7 | "dev": "npm run build && npm run start", 8 | "build": "echo 'Building...' && webpack", 9 | "start": "electron build/main.bundle.js", 10 | "watch": "./node_modules/.bin/webpack-dev-server --port 8182" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/jogleasonjr/electron-react-webpack-quick-start.git" 15 | }, 16 | "keywords": [ 17 | "Electron", 18 | "quick", 19 | "start", 20 | "tutorial", 21 | "es6", 22 | "es2015", 23 | "react", 24 | "webpack" 25 | ], 26 | "author": "John Gleason", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/jogleasonjr/electron-react-webpack-quick-start/issues" 30 | }, 31 | "homepage": "https://github.com/jogleasonjr/electron-react-webpack-quick-start#readme", 32 | "devDependencies": { 33 | "babel-core": "^6.5.2", 34 | "babel-loader": "^6.2.2", 35 | "babel-preset-es2015": "^6.5.0", 36 | "babel-preset-react": "^6.5.0", 37 | "css-loader": "^0.23.1", 38 | "electron-prebuilt": "^0.36.0", 39 | "eslint": "^2.1.0", 40 | "eslint-loader": "^1.2.1", 41 | "node-sass": "^3.4.2", 42 | "sass-loader": "^3.1.2", 43 | "style-loader": "^0.13.0", 44 | "webpack": "^1.12.14", 45 | "webpack-dev-server": "^1.14.1" 46 | }, 47 | "dependencies": { 48 | "react": "^0.14.7", 49 | "react-dom": "^0.14.7" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # electron-react-webpack-quick-start 2 | 3 | A minimal, cross-platform Electron application with [React](https://facebook.github.io/react/) for views and [Webpack](https://webpack.github.io/). Set breakpoints and debug the main process with [Visual Studio Code](https://code.visualstudio.com/). ES6/ES2015 support using [Babel](https://babeljs.io/). 4 | 5 | ![Image](https://github.com/jogleasonjr/electron-react-webpack-quick-start/blob/master/images/hello_world.png) 6 | 7 | ## To Build and Run via CLI 8 | 9 | ```bash 10 | # Clone this repository 11 | git clone https://github.com/jogleasonjr/electron-react-webpack-quick-start 12 | # Go into the repository 13 | cd electron-react-webpack-quick-start 14 | # Install dependencies and run the app 15 | npm install && npm run dev 16 | ``` 17 | 18 | ### Hot Reloading 19 | 20 | To watch for local changes and trigger [automatic refresh](https://webpack.github.io/docs/webpack-dev-server.html#automatic-refresh), run these two commands in separate console windows: 21 | 22 | ```bash 23 | # Run in console window 1 24 | npm run watch 25 | # Run in console window 2 26 | npm run dev 27 | ``` 28 | 29 | ## To Build and Run in Visual Studio Code 30 | 31 | In [Visual Studio Code](https://code.visualstudio.com/), pressing `Ctrl-Shift-B` (Windows) or `Cmd-Shift-B` (OSX) will build and bundle the application, and pressing `F5` will debug the application. Make sure you have the proper OS selection in the VS Code's [Debug View](https://code.visualstudio.com/Docs/editor/debugging). 32 | 33 | ![Image](https://github.com/jogleasonjr/electron-react-webpack-quick-start/blob/master/images/vscode_debugger.png) 34 | 35 | ## Next Steps 36 | 37 | Learn more about Electron and its API in the [documentation](http://electron.atom.io/docs/latest). 38 | 39 | Learn more about React and JSX components [here](https://facebook.github.io/react/docs/getting-started.html). 40 | 41 | ## License 42 | 43 | [MIT](https://tldrlegal.com/license/mit-license) 44 | -------------------------------------------------------------------------------- /app/main/main.js: -------------------------------------------------------------------------------- 1 | import electron from 'electron'; 2 | 3 | // Module to control application life. 4 | const app = electron.app; 5 | // Module to create native browser window. 6 | const BrowserWindow = electron.BrowserWindow; 7 | // Modules for React.js 8 | 9 | // Keep a global reference of the window object, if you don't, the window will 10 | // be closed automatically when the JavaScript object is garbage collected. 11 | let mainWindow; 12 | 13 | function createWindow() { 14 | // Create the browser window. 15 | mainWindow = new BrowserWindow({ width: 1360, height: 800 }); 16 | 17 | // Load the index.html of the app. 18 | // Most examples use __dirname instead of process.cwd(). 19 | // However Webpack, at least by default, injects "" as 20 | // the __dirname parameter in the bundled file. So to keep 21 | // things working both in regular electron usage AND webpack, 22 | // we have to go with process.cwd() instead of __dirname. 23 | mainWindow.loadURL('file://' + process.cwd() + '/app/renderer/public/index.html'); 24 | 25 | 26 | // Open the DevTools. 27 | mainWindow.webContents.openDevTools(); 28 | 29 | // Emitted when the window is closed. 30 | mainWindow.on('closed', function () { 31 | // Dereference the window object, usually you would store windows 32 | // in an array if your app supports multi windows, this is the time 33 | // when you should delete the corresponding element. 34 | mainWindow = null; 35 | }); 36 | } 37 | 38 | // This method will be called when Electron has finished 39 | // initialization and is ready to create browser windows. 40 | app.on('ready', createWindow); 41 | 42 | // Quit when all windows are closed. 43 | app.on('window-all-closed', function () { 44 | // On OS X it is common for applications and their menu bar 45 | // to stay active until the user quits explicitly with Cmd + Q 46 | if (process.platform !== 'darwin') { 47 | app.quit(); 48 | } 49 | }); 50 | 51 | app.on('activate', function () { 52 | // On OS X it's common to re-create a window in the app when the 53 | // dock icon is clicked and there are no other windows open. 54 | if (mainWindow === null) { 55 | createWindow(); 56 | } 57 | }); 58 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | 4 | module.exports = { 5 | 6 | // This is the setting for electron. 7 | target: "electron", 8 | 9 | // This enables the creation of source maps, 10 | // which improve the debuggability of the application 11 | // by allowing you to see where an error was raised. 12 | devtool: "source-map", 13 | 14 | // Entry file to startsbuilding from. 15 | // entry.jsx is the renderer process, 16 | // main.js is for the main process. 17 | // Electron will be pointed at the main bundle, 18 | // while the Renderer will point to entry bundle. 19 | entry: { 20 | entry: './app/renderer/entry.jsx', 21 | main: './app/main/main.js' 22 | }, 23 | 24 | // Location and filename pattern of the 25 | // final build output files. 26 | output: { 27 | path: path.join(__dirname, 'build'), 28 | filename: "[name].bundle.js" 29 | }, 30 | 31 | devServer: { 32 | //content from here will be automatically served 33 | contentBase: './app/renderer/public', 34 | publicPath: 'http://localhost:8182/build/' 35 | }, 36 | 37 | 38 | module: { 39 | preLoaders: [ 40 | // Performs linting on code for quality checks 41 | { 42 | test: /(\.js$|\.jsx$)/, 43 | include: path.resolve(__dirname, "app"), 44 | loader: "eslint" 45 | } 46 | ], 47 | loaders: [ 48 | { 49 | // Post-css loader and its plugins. 50 | test: /\.scss$/, 51 | include: path.resolve(__dirname, "app/renderer/styles"), 52 | loaders: [ 53 | 'style',// inserts raw css into styles elements. 54 | 'css', // css-loader parses css files resolves url() expressions. 55 | 'sass' // sass-loader for sass compilation 56 | ] 57 | }, 58 | { 59 | // Babel loader configuration. Performs the JSX and ES6 to JS transformations. 60 | test: /\.jsx?$/, 61 | include: path.resolve(__dirname, "app"), 62 | loader: 'babel', 63 | query: { 64 | presets: ['react', 'es2015'] 65 | } 66 | }] 67 | }, 68 | 69 | eslint: { 70 | configFile: '.eslintrc' 71 | }, 72 | 73 | // Defines where we can load modules from, 74 | // and the extensions we care about. The '' 75 | // empty string allows the requiring of arbitrary 76 | // extensions, e.g. require('./somefile.ext'). 77 | // Specifiying extensions such as '.js' allows 78 | // requiring without extensions, 79 | // e.g. require('underscore') 80 | resolve: { 81 | modulesDirectories: ['node_modules'], 82 | extensions: ['', '.js', '.jsx'] 83 | }, 84 | 85 | plugins: [ 86 | new webpack.HotModuleReplacementPlugin() 87 | ] 88 | } --------------------------------------------------------------------------------