├── .eslintignore
├── .gitignore
├── src
├── layouts
│ ├── MainLayout.scss
│ ├── ContentRoutes.scss
│ ├── HeaderBar.scss
│ ├── SideMenu.scss
│ ├── HeaderBar.js
│ ├── MainLayout.js
│ ├── ContentRoutes.js
│ └── SideMenu.js
├── styles
│ ├── index.js
│ ├── default.less
│ └── default.scss
├── pages
│ ├── HomePage.scss
│ ├── NotFoundPage.js
│ ├── AboutPage.js
│ └── HomePage.js
├── index.js
├── App.js
└── components
│ ├── PieChart.js
│ └── LineChart.js
├── .vscode
├── settings.json
└── launch.json
├── screenshot
└── screen.png
├── template
└── index.html
├── .babelrc
├── .compilerc
├── LICENSE
├── webpack.common.js
├── .eslintrc
├── webpack.prod.js
├── README.md
├── webpack.dev.js
├── app
└── index.js
└── package.json
/.eslintignore:
--------------------------------------------------------------------------------
1 | dist/
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | out
3 | dist
4 | .eslintcache
5 | .cache
6 |
--------------------------------------------------------------------------------
/src/layouts/MainLayout.scss:
--------------------------------------------------------------------------------
1 | .layout {
2 | height: 100%;
3 | }
4 |
--------------------------------------------------------------------------------
/src/styles/index.js:
--------------------------------------------------------------------------------
1 | import './default.less';
2 | import './default.scss';
3 |
--------------------------------------------------------------------------------
/src/layouts/ContentRoutes.scss:
--------------------------------------------------------------------------------
1 | .content {
2 | margin: 24px 24px 0px;
3 | height: 100%;
4 | }
5 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.eol": "\n",
3 | "editor.insertSpaces": true,
4 | "editor.tabSize": 4
5 | }
--------------------------------------------------------------------------------
/screenshot/screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/electron-webpack-react-boilerplate/HEAD/screenshot/screen.png
--------------------------------------------------------------------------------
/src/layouts/HeaderBar.scss:
--------------------------------------------------------------------------------
1 | .bar {
2 | background-color: #fff;
3 | padding-left: 16px;
4 | font-size: 18px;
5 | }
6 |
--------------------------------------------------------------------------------
/src/styles/default.less:
--------------------------------------------------------------------------------
1 | @import "~antd/dist/antd.less"; // import official less entry file
2 |
3 | @primary-color: green;
4 |
--------------------------------------------------------------------------------
/src/styles/default.scss:
--------------------------------------------------------------------------------
1 | :global {
2 | html body #root {
3 | background-color: #fff;
4 | margin: 0px;
5 | padding: 0px;
6 | height: 100%;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/pages/HomePage.scss:
--------------------------------------------------------------------------------
1 | .titleCard {
2 | padding-left: 12px;
3 | padding-right: 12px;
4 | margin-bottom: 24px;
5 | }
6 |
7 | .tileRow {
8 | margin-left: -12px;
9 | margin-right: -12px;
10 | }
11 |
--------------------------------------------------------------------------------
/src/layouts/SideMenu.scss:
--------------------------------------------------------------------------------
1 | .logo {
2 | height: 48px;
3 | line-height: 48px;
4 | background: rgba(255, 255, 255, 0.2);
5 | margin: 16px;
6 | padding: 16;
7 | text-align: center;
8 |
9 | a {
10 | color: #fff;
11 | text-decoration: none;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/pages/NotFoundPage.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | export default class NotFoundPage extends Component {
4 |
5 | state = {}
6 |
7 | render() {
8 | return (
9 |
10 | 404
11 |
12 | );
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/template/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | <%= htmlWebpackPlugin.options.title %>
8 |
9 |
10 |
11 | Loading...
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "react",
4 | "es2015",
5 | "stage-2"
6 | ],
7 | "plugins": [
8 | "transform-class-properties"
9 | ],
10 | "env": {
11 | "development": {
12 | "plugins": [
13 | "react-hot-loader/babel"
14 | ]
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 |
4 | import './styles';
5 | import App from './App';
6 |
7 | window.Promise = require('bluebird');
8 | window.axios = require('axios').default;
9 | window.moment = require('moment-timezone');
10 | require('moment/locale/pt-br'); // eslint-disable-line import/no-extraneous-dependencies
11 |
12 | ReactDOM.render(
13 | ,
14 | document.getElementById('root'),
15 | );
16 |
--------------------------------------------------------------------------------
/.compilerc:
--------------------------------------------------------------------------------
1 | {
2 | "application/javascript": {
3 | "presets": [
4 | "react",
5 | "es2015",
6 | "stage-2"
7 | ],
8 | "plugins": [
9 | "transform-class-properties"
10 | ],
11 | "env": {
12 | "development": {
13 | "plugins": [
14 | "react-hot-loader/babel"
15 | ],
16 | "sourceMaps": "both"
17 | },
18 | "production": {
19 | "sourceMaps": "none"
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/layouts/HeaderBar.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import { Layout, Icon } from 'antd';
4 |
5 | import styles from './HeaderBar.scss';
6 |
7 | const { Header } = Layout;
8 |
9 | export default class HeaderBar extends Component {
10 |
11 | state = {}
12 |
13 | render() {
14 | return (
15 |
16 |
17 |
18 |
19 |
20 | My Project
21 |
22 |
23 |
24 | );
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import { HashRouter } from 'react-router-dom';
4 | import { hot } from 'react-hot-loader';
5 | import { LocaleProvider } from 'antd';
6 | import ptBR from 'antd/lib/locale-provider/pt_BR';
7 |
8 | import MainLayout from './layouts/MainLayout';
9 |
10 | class App extends Component {
11 |
12 | state = {};
13 |
14 | render() {
15 | return (
16 |
17 |
18 |
19 |
20 |
21 | );
22 | }
23 |
24 | }
25 |
26 | export default hot(module)(App);
27 |
--------------------------------------------------------------------------------
/src/layouts/MainLayout.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import { Layout } from 'antd';
4 |
5 | import styles from './MainLayout.scss';
6 | import HeaderBar from './HeaderBar';
7 | import ContentRoutes from './ContentRoutes';
8 | import SideMenu from './SideMenu';
9 |
10 | export default class MainLayout extends Component {
11 |
12 | state = {}
13 |
14 | render() {
15 | return (
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | );
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "type": "node",
9 | "request": "launch",
10 | "name": "Electron Debug",
11 | "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-forge-vscode-nix",
12 | "windows": {
13 | "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-forge-vscode-win.cmd"
14 | },
15 | // runtimeArgs will be passed directly to your Electron application
16 | "runtimeArgs": [],
17 | "cwd": "${workspaceRoot}"
18 | }
19 | ]
20 | }
--------------------------------------------------------------------------------
/src/pages/AboutPage.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import { Layout } from 'antd';
4 |
5 | const { Content } = Layout;
6 |
7 | export default class AboutPage extends Component {
8 |
9 | state = {}
10 |
11 | render() {
12 | return (
13 |
14 | About
15 |
16 |
17 | Sample project using Electron Forge + webpack + React + React Router
18 | + Ant Design + Recharts + Sass and Less.
19 |
20 |
21 | Source code on
22 |
23 | GitHib Repo
24 |
25 | .
26 |
27 |
28 | );
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Douglas Nassif Roma Junior
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 all
13 | 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 THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/webpack.common.js:
--------------------------------------------------------------------------------
1 | const HtmlWebpackPlugin = require('html-webpack-plugin'); // eslint-disable-line
2 | const CleanWebpackPlugin = require('clean-webpack-plugin'); // eslint-disable-line
3 |
4 | module.exports = {
5 | entry: ['babel-polyfill', './src/index.js'],
6 | target: 'electron-main',
7 | plugins: [
8 | new CleanWebpackPlugin(['dist/**/*']),
9 | new HtmlWebpackPlugin({
10 | template: './template/index.html',
11 | title: 'My Project',
12 | }),
13 | ],
14 | module: {
15 | rules: [
16 | {
17 | test: /\.(png|svg|jpg|gif)$/,
18 | use: ['file-loader'],
19 | },
20 | {
21 | enforce: 'pre',
22 | test: /\.jsx?$/,
23 | exclude: /(node_modules|bower_components)/,
24 | loader: 'eslint-loader',
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | exclude: /(node_modules|bower_components)/,
29 | use: {
30 | loader: 'babel-loader',
31 | },
32 | },
33 | ],
34 | },
35 | resolve: {
36 | extensions: ['.js', '.jsx', '.less', '.json'],
37 | },
38 | };
39 |
--------------------------------------------------------------------------------
/src/layouts/ContentRoutes.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import { Layout } from 'antd';
4 | import { Switch, Route } from 'react-router-dom';
5 |
6 | import styles from './ContentRoutes.scss';
7 |
8 | import HomePage from '../pages/HomePage';
9 | import AboutPage from '../pages/AboutPage';
10 | import NotFoundPage from '../pages/NotFoundPage';
11 |
12 | const { Content } = Layout;
13 |
14 | export const ROUTES_ITEMS = [
15 | {
16 | to: '/',
17 | text: 'Home',
18 | icon: 'home',
19 | exact: true,
20 | component: HomePage,
21 | }, {
22 | to: '/about',
23 | text: 'About',
24 | icon: 'info-circle-o',
25 | component: AboutPage,
26 | },
27 | ];
28 |
29 | const ROUTES = ROUTES_ITEMS.map(route => (
30 |
31 | ));
32 |
33 | export default class ContentRoutes extends Component {
34 |
35 | state = {};
36 |
37 | render() {
38 | return (
39 |
40 |
41 |
42 | {ROUTES}
43 |
44 |
45 |
46 |
47 |
48 | );
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/components/PieChart.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import {
4 | PieChart as PC, Pie,
5 | ResponsiveContainer, Cell,
6 | } from 'recharts';
7 |
8 | const data = [
9 | { name: 'Group A', value: 400 },
10 | { name: 'Group B', value: 300 },
11 | { name: 'Group C', value: 300 },
12 | { name: 'Group D', value: 200 },
13 | ];
14 |
15 | const COLORS = ['#0088FE', '#00C49F', '#FFBB28', '#FF8042'];
16 |
17 | export default class PieChart extends Component {
18 |
19 | constructor(props) {
20 | super(props);
21 |
22 | this.state = {};
23 | }
24 |
25 | render() {
26 | return (
27 |
28 |
29 |
41 | {
42 | data.map((entry, index) => (
43 | |
44 | ))
45 | }
46 |
47 |
48 |
49 | );
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/pages/HomePage.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import { Card, Row, Col } from 'antd';
4 |
5 | import styles from './HomePage.scss';
6 | import LineChart from '../components/LineChart';
7 | import PieChart from '../components/PieChart';
8 |
9 | export default class HomePage extends Component {
10 |
11 | constructor(props) {
12 | super(props);
13 | this.state = {};
14 | }
15 |
16 | render() {
17 | return (
18 |
19 |
Dashboard
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | );
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "extends": [
4 | "airbnb"
5 | ],
6 | "globals": {
7 | "document": false,
8 | "window": false
9 | },
10 | "rules": {
11 | "indent": [
12 | "error",
13 | 4,
14 | {
15 | "SwitchCase": 1
16 | }
17 | ],
18 | "semi": [
19 | "error",
20 | "always"
21 | ],
22 | "no-underscore-dangle": [
23 | "error",
24 | {
25 | "allowAfterThis": true
26 | }
27 | ],
28 | "arrow-parens": [
29 | "warn",
30 | "as-needed"
31 | ],
32 | "max-len": [
33 | "warn",
34 | 120
35 | ],
36 | "padded-blocks": [
37 | "error",
38 | {
39 | "classes": "always"
40 | }
41 | ],
42 | "no-nested-ternary": "off",
43 | "global-require": "off",
44 | "no-unused-vars": [
45 | "error",
46 | {
47 | "args": "none"
48 | }
49 | ],
50 | "react/require-default-props": "warn",
51 | "react/prop-types": "warn",
52 | "react/no-string-refs": "warn",
53 | "react/jsx-filename-extension": [
54 | "error",
55 | {
56 | "extensions": [
57 | ".js",
58 | ".jsx"
59 | ]
60 | }
61 | ],
62 | "react/jsx-indent": [
63 | "error",
64 | 4
65 | ],
66 | "react/jsx-indent-props": [
67 | "error",
68 | 4
69 | ],
70 | "react/no-unused-state": "warn",
71 | "jsx-a11y/anchor-is-valid": "off",
72 | "jsx-a11y/click-events-have-key-events": "off",
73 | "no-console": [
74 | "error",
75 | {
76 | "allow": [
77 | "warn"
78 | ]
79 | }
80 | ],
81 | "import/no-extraneous-dependencies": "off"
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/components/LineChart.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import {
4 | LineChart as LC, Line, XAxis, YAxis, CartesianGrid,
5 | Tooltip, Legend, ResponsiveContainer,
6 | } from 'recharts';
7 |
8 | const data = [
9 | {
10 | name: 'Page A', uv: 4000, pv: 2400, amt: 2400,
11 | },
12 | {
13 | name: 'Page B', uv: 3000, pv: 1398, amt: 2210,
14 | },
15 | {
16 | name: 'Page C', uv: 2000, pv: 9800, amt: 2290,
17 | },
18 | {
19 | name: 'Page D', uv: 2780, pv: 3908, amt: 2000,
20 | },
21 | {
22 | name: 'Page E', uv: 1890, pv: 4800, amt: 2181,
23 | },
24 | {
25 | name: 'Page F', uv: 2390, pv: 3800, amt: 2500,
26 | },
27 | {
28 | name: 'Page G', uv: 3490, pv: 4300, amt: 2100,
29 | },
30 | ];
31 |
32 | export default class LineChart extends Component {
33 |
34 | constructor(props) {
35 | super(props);
36 | this.state = {};
37 | }
38 |
39 | render() {
40 | return (
41 |
42 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | );
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/webpack.prod.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const merge = require('webpack-merge');
3 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
4 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
5 | const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
6 |
7 | const common = require('./webpack.common.js');
8 |
9 | module.exports = merge(common, {
10 | output: {
11 | path: path.resolve(__dirname, 'dist'),
12 | filename: 'bundle.js',
13 | },
14 | mode: 'production',
15 | plugins: [
16 | new MiniCssExtractPlugin({
17 | filename: 'bundle.css',
18 | }),
19 | new OptimizeCSSAssetsPlugin(),
20 | new UglifyJsPlugin({
21 | parallel: true,
22 | }),
23 | ],
24 | module: {
25 | rules: [
26 | {
27 | test: /\.s?css$/,
28 | use: [
29 | MiniCssExtractPlugin.loader,
30 | {
31 | loader: 'css-loader',
32 | options: {
33 | modules: true,
34 | localIdentName: '[name]_[local]_[hash:base64:10]',
35 | importLoaders: 2,
36 | },
37 | }, {
38 | loader: 'sass-loader',
39 | },
40 | ],
41 | }, {
42 | test: /\.less$/,
43 | use: [
44 | MiniCssExtractPlugin.loader,
45 | {
46 | loader: 'css-loader',
47 | }, {
48 | loader: 'less-loader',
49 | options: {
50 | javascriptEnabled: true,
51 | },
52 | },
53 | ],
54 | },
55 | ],
56 | },
57 | });
58 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Complete Electron, webpack and React boilerplate
2 |
3 | Sample project containing Electron Forge + webpack + React + React Router + Ant Design + Recharts + Sass and Less.
4 |
5 | ## Screenshot
6 |
7 | 
8 |
9 | ## Technologies included
10 |
11 | - [Electron Forge](https://electronforge.io/)
12 | - The command line interface for ambitious Electron applications.
13 | - [webpack](https://webpack.js.org/)
14 | - A bundler for javascript and friends.
15 | - [React JS](https://reactjs.org/)
16 | - A JavaScript library for building user interfaces.
17 | - [React Router](https://reacttraining.com/react-router/)
18 | - Declarative routing for React.
19 | - [Ant Design](https://ant.design/)
20 | - A design system with values of Nature and Determinacy for better user experience of enterprise applications.
21 | - [Recharts](http://recharts.org/)
22 | - A composable charting library built on React components.
23 |
24 | ## Download
25 |
26 | ```bash
27 | $ git clone https://github.com/douglasjunior/electron-webpack-react-boilerplate.git
28 | $ cd electron-webpack-react-boilerplate
29 | $ npm install
30 | ```
31 |
32 | ## Usage:
33 |
34 | Start development mode:
35 | ```bash
36 | $ npm start
37 | ```
38 |
39 | Create package for the current platform:
40 | ```bash
41 | $ npm run build
42 | ```
43 |
44 | Build for Mac OSX: (only works on Mac)
45 | ```bash
46 | $ npm run make:mac
47 | ```
48 |
49 | Build for Linux (deb and dpkg): (works on Linux or Mac)
50 | ```bash
51 | $ npm run make:linux
52 | ```
53 |
54 | Build for Windows: (only works on Windows)
55 | ```bash
56 | $ npm run make:windows
57 | ```
58 |
59 | _For a complete list of *Electron Forge* options and requirements, visit the [official docs](https://github.com/electron-userland/electron-forge#usage)._
60 |
61 | ## License
62 |
63 | MIT License
64 |
65 | Copyright (c) 2018 Douglas Nassif Roma Junior
66 |
--------------------------------------------------------------------------------
/src/layouts/SideMenu.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import PropTypes from 'prop-types';
4 | import { Layout, Menu, Icon } from 'antd';
5 | import { Link, withRouter } from 'react-router-dom';
6 |
7 | import styles from './SideMenu.scss';
8 | import { ROUTES_ITEMS } from './ContentRoutes';
9 |
10 | const { Sider } = Layout;
11 |
12 | class SideMenu extends Component {
13 |
14 | state = {
15 | collapsed: false,
16 | };
17 |
18 | _onCollapse = (collapsed, type) => {
19 | this.setState({ collapsed });
20 | }
21 |
22 | render() {
23 | const { collapsed } = this.state;
24 | const { location } = this.props;
25 |
26 | const menuItems = ROUTES_ITEMS.map(item => (
27 |
28 |
29 |
30 |
31 | {item.text}
32 |
33 |
34 |
35 | ));
36 |
37 | return (
38 |
44 |
45 |
46 |
47 | Project
48 |
49 |
50 |
51 |
61 |
62 |
63 | );
64 | }
65 |
66 | }
67 |
68 | PropTypes.toString();
69 |
70 | SideMenu.propTypes = {
71 | location: PropTypes.shape({
72 | pathname: PropTypes.string.isRequired,
73 | }).isRequired,
74 | };
75 |
76 | export default withRouter(SideMenu);
77 |
--------------------------------------------------------------------------------
/webpack.dev.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const webpack = require('webpack'); // eslint-disable-line
3 | const merge = require('webpack-merge'); // eslint-disable-line
4 | const common = require('./webpack.common.js');
5 |
6 | module.exports = merge(common, {
7 | output: {
8 | path: path.resolve(__dirname, 'dist'),
9 | filename: 'bundle.js',
10 | },
11 | mode: 'development',
12 | devtool: 'eval-source-map',
13 | devServer: {
14 | contentBase: './dist',
15 | port: 8081,
16 | hot: true,
17 | },
18 | plugins: [
19 | new webpack.NamedModulesPlugin(),
20 | new webpack.HotModuleReplacementPlugin(),
21 | ],
22 | module: {
23 | rules: [
24 | {
25 | test: /\.s?css$/,
26 | use: [
27 | {
28 | loader: 'style-loader',
29 | options: {
30 | sourceMap: true,
31 | },
32 | }, {
33 | loader: 'css-loader',
34 | options: {
35 | sourceMap: true,
36 | modules: true,
37 | localIdentName: '[name]_[local]_[hash:base64:10]',
38 | importLoaders: 1,
39 | },
40 | }, {
41 | loader: 'sass-loader',
42 | options: {
43 | sourceMap: true,
44 | },
45 | },
46 | ],
47 | }, {
48 | test: /\.less$/,
49 | use: [
50 | {
51 | loader: 'style-loader',
52 | options: {
53 | sourceMap: true,
54 | },
55 | }, {
56 | loader: 'css-loader',
57 | options: {
58 | sourceMap: true,
59 | },
60 | }, {
61 | loader: 'less-loader',
62 | options: {
63 | sourceMap: true,
64 | javascriptEnabled: true,
65 | },
66 | },
67 | ],
68 | },
69 | ],
70 | },
71 | });
72 |
--------------------------------------------------------------------------------
/app/index.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable global-require */
2 |
3 | import path from 'path';
4 | import { app, BrowserWindow } from 'electron';
5 |
6 | // Handle creating/removing shortcuts on Windows when installing/uninstalling.
7 | if (require('electron-squirrel-startup')) {
8 | app.quit();
9 | }
10 |
11 | const isDevMode = process.execPath.match(/[\\/]node_modules\/electron/);
12 |
13 | // Keep a global reference of the window object, if you don't, the window will
14 | // be closed automatically when the JavaScript object is garbage collected.
15 | let mainWindow;
16 |
17 | const createWindow = () => {
18 | // Create the browser window.
19 | mainWindow = new BrowserWindow({
20 | width: 800,
21 | height: 600,
22 | });
23 |
24 | // mainWindow.maximize();
25 |
26 | // and load the index.html of the app.
27 | if (isDevMode) {
28 | mainWindow.loadURL('http://localhost:8081/');
29 | } else {
30 | mainWindow.loadURL(`file://${path.resolve(__dirname, '..', 'dist')}/index.html`);
31 | }
32 |
33 | // Emitted when the window is closed.
34 | mainWindow.on('closed', () => {
35 | // Dereference the window object, usually you would store windows
36 | // in an array if your app supports multi windows, this is the time
37 | // when you should delete the corresponding element.
38 | mainWindow = null;
39 | });
40 |
41 | // Open the DevTools.
42 | if (isDevMode) {
43 | const { enableLiveReload } = require('electron-compile');
44 | const { REACT_DEVELOPER_TOOLS, default: installExtension } = require('electron-devtools-installer');
45 |
46 | enableLiveReload({ strategy: 'react-hmr' });
47 | installExtension(REACT_DEVELOPER_TOOLS).then(() => {
48 | mainWindow.webContents.openDevTools();
49 | });
50 | }
51 | };
52 |
53 | // This method will be called when Electron has finished
54 | // initialization and is ready to create browser windows.
55 | // Some APIs can only be used after this event occurs.
56 | app.on('ready', createWindow);
57 |
58 | // Quit when all windows are closed.
59 | app.on('window-all-closed', () => {
60 | // On OS X it is common for applications and their menu bar
61 | // to stay active until the user quits explicitly with Cmd + Q
62 | if (process.platform !== 'darwin') {
63 | app.quit();
64 | }
65 | });
66 |
67 | app.on('activate', () => {
68 | // On OS X it's common to re-create a window in the app when the
69 | // dock icon is clicked and there are no other windows open.
70 | if (mainWindow === null) {
71 | createWindow();
72 | }
73 | });
74 |
75 | // In this file you can include the rest of your app's specific main process
76 | // code. You can also put them in separate files and import them here.
77 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "electron-webpack-react-boilerplate",
3 | "productName": "My Project",
4 | "version": "1.0.0",
5 | "description": "My Project",
6 | "main": "app/index.js",
7 | "private": true,
8 | "scripts": {
9 | "start": "run-p webpack forge:start",
10 | "build": "run-s webpack:build forge:package",
11 | "forge:start": "electron-forge start",
12 | "forge:package": "electron-forge package",
13 | "make:mac": "electron-forge make --platform=darwin",
14 | "make:linux": "electron-forge make --platform=linux --arch=ia32,x64",
15 | "make:windows": "electron-forge make --platform=win32 --arch=ia32,x64",
16 | "webpack": "webpack-dev-server --config webpack.dev.js",
17 | "webpack:build": "webpack --progress --config webpack.prod.js",
18 | "publish": "electron-forge publish",
19 | "lint": "eslint . --cache --color"
20 | },
21 | "keywords": [],
22 | "author": {
23 | "name": "Douglas Nassif Roma Junior",
24 | "email": "nassifrroma@gmail.com",
25 | "url": "http://douglasjunior.me"
26 | },
27 | "license": "MIT",
28 | "config": {
29 | "forge": {
30 | "make_targets": {
31 | "win32": [
32 | "wix"
33 | ],
34 | "darwin": [
35 | "dmg"
36 | ],
37 | "linux": [
38 | "deb",
39 | "rpm"
40 | ]
41 | },
42 | "electronPackagerConfig": {
43 | "packageManager": "yarn",
44 | "asar": true,
45 | "arch": "all",
46 | "ignore": [
47 | ".vscode",
48 | ".cache",
49 | "src",
50 | "template",
51 | "out",
52 | "screenshot"
53 | ]
54 | },
55 | "electronWinstallerConfig": {
56 | "name": "My Project"
57 | },
58 | "electronWixMSIConfig": {
59 | "name": "My Project",
60 | "appUserModelId": "com.my-project",
61 | "manufacturer": "My Project",
62 | "ui": {
63 | "enabled": true,
64 | "chooseDirectory": true
65 | }
66 | },
67 | "electronInstallerDebian": {},
68 | "electronInstallerRedhat": {},
69 | "github_repository": {
70 | "owner": "douglasjunior",
71 | "name": "electron-webpack-react-boilerplate"
72 | },
73 | "windowsStoreConfig": {
74 | "packageName": "com.my-project",
75 | "name": "My Project"
76 | }
77 | }
78 | },
79 | "husky": {
80 | "hooks": {
81 | "pre-push": "npm run lint"
82 | }
83 | },
84 | "dependencies": {
85 | "electron-compile": "6.4.3",
86 | "electron-squirrel-startup": "1.0.0",
87 | "react-hot-loader": "4.3.5"
88 | },
89 | "devDependencies": {
90 | "antd": "3.8.4",
91 | "axios": "0.18.0",
92 | "bluebird": "3.5.1",
93 | "moment-timezone": "0.5.21",
94 | "prop-types": "15.6.2",
95 | "react": "16.4.2",
96 | "react-dom": "16.4.2",
97 | "react-router-dom": "4.3.1",
98 | "recharts": "1.1.0",
99 | "babel-core": "6.26.3",
100 | "babel-eslint": "9.0.0",
101 | "babel-loader": "7.1.5",
102 | "babel-plugin-import": "1.8.0",
103 | "babel-plugin-transform-class-properties": "6.24.1",
104 | "babel-polyfill": "6.26.0",
105 | "babel-preset-es2015": "6.24.1",
106 | "babel-preset-react": "6.24.1",
107 | "babel-preset-stage-2": "6.24.1",
108 | "clean-webpack-plugin": "0.1.19",
109 | "cross-env": "5.2.0",
110 | "css-loader": "1.0.0",
111 | "electron-devtools-installer": "2.2.4",
112 | "electron-forge": "5.2.2",
113 | "electron-prebuilt-compile": "2.0.7",
114 | "electron-wix-msi": "1.3.0",
115 | "eslint": "5.5.0",
116 | "eslint-config-airbnb": "17.1.0",
117 | "eslint-loader": "2.1.0",
118 | "eslint-plugin-import": "2.14.0",
119 | "eslint-plugin-jsx-a11y": "6.1.1",
120 | "eslint-plugin-react": "7.11.1",
121 | "html-webpack-plugin": "3.2.0",
122 | "husky": "1.0.0-rc.13",
123 | "less": "3.8.1",
124 | "less-loader": "4.1.0",
125 | "mini-css-extract-plugin": "0.4.1",
126 | "node-sass": "4.9.3",
127 | "npm-run-all": "4.1.3",
128 | "optimize-css-assets-webpack-plugin": "5.0.0",
129 | "sass-loader": "7.1.0",
130 | "style-loader": "0.23.0",
131 | "uglifyjs-webpack-plugin": "1.3.0",
132 | "webpack": "4.17.1",
133 | "webpack-cli": "3.1.0",
134 | "webpack-dev-server": "3.1.7",
135 | "webpack-merge": "4.1.4"
136 | }
137 | }
138 |
--------------------------------------------------------------------------------