├── .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 | 
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 | 
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 | }
--------------------------------------------------------------------------------