├── .erb ├── mocks │ └── fileMock.js ├── img │ ├── erb-logo.png │ └── erb-banner.png ├── configs │ ├── .eslintrc │ ├── webpack.config.eslint.ts │ ├── postcss.config.js │ ├── webpack.config.base.ts │ ├── webpack.paths.ts │ ├── webpack.config.renderer.dev.dll.ts │ ├── webpack.config.main.prod.ts │ ├── webpack.config.renderer.prod.ts │ └── webpack.config.renderer.dev.ts └── scripts │ ├── .eslintrc │ ├── link-modules.js │ ├── delete-source-maps.js │ ├── check-node-env.js │ ├── clean.js │ ├── check-port-in-use.js │ ├── electron-rebuild.js │ ├── check-build-exists.ts │ ├── notarize.js │ └── check-native-dep.js ├── assets ├── icon.icns ├── icon.ico ├── icon.png ├── icons │ ├── 16x16.png │ ├── 24x24.png │ ├── 32x32.png │ ├── 48x48.png │ ├── 64x64.png │ ├── 96x96.png │ ├── 1024x1024.png │ ├── 128x128.png │ ├── 256x256.png │ └── 512x512.png ├── assets.d.ts ├── entitlements.mac.plist └── icon.svg ├── .vscode ├── extensions.json ├── settings.json ├── tasks.json └── launch.json ├── src ├── renderer │ ├── index.tsx │ ├── index.ejs │ ├── App.css │ └── App.tsx ├── __tests__ │ └── App.test.tsx └── main │ ├── util.ts │ ├── preload.js │ ├── main.ts │ └── menu.ts ├── .github ├── config.yml ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── 3-Feature_request.md │ ├── 2-Question.md │ └── 1-Bug_report.md ├── stale.yml └── workflows │ ├── test.yml │ └── publish.yml ├── .editorconfig ├── .gitattributes ├── README.md ├── release └── app │ ├── package-lock.json │ └── package.json ├── tailwind.config.js ├── .gitignore ├── .eslintignore ├── tsconfig.json ├── .eslintrc.js ├── LICENSE ├── CODE_OF_CONDUCT.md ├── package.json └── CHANGELOG.md /.erb/mocks/fileMock.js: -------------------------------------------------------------------------------- 1 | export default 'test-file-stub'; 2 | -------------------------------------------------------------------------------- /assets/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amilajack/erb-tailwind-example/HEAD/assets/icon.icns -------------------------------------------------------------------------------- /assets/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amilajack/erb-tailwind-example/HEAD/assets/icon.ico -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amilajack/erb-tailwind-example/HEAD/assets/icon.png -------------------------------------------------------------------------------- /.erb/img/erb-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amilajack/erb-tailwind-example/HEAD/.erb/img/erb-logo.png -------------------------------------------------------------------------------- /.erb/img/erb-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amilajack/erb-tailwind-example/HEAD/.erb/img/erb-banner.png -------------------------------------------------------------------------------- /assets/icons/16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amilajack/erb-tailwind-example/HEAD/assets/icons/16x16.png -------------------------------------------------------------------------------- /assets/icons/24x24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amilajack/erb-tailwind-example/HEAD/assets/icons/24x24.png -------------------------------------------------------------------------------- /assets/icons/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amilajack/erb-tailwind-example/HEAD/assets/icons/32x32.png -------------------------------------------------------------------------------- /assets/icons/48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amilajack/erb-tailwind-example/HEAD/assets/icons/48x48.png -------------------------------------------------------------------------------- /assets/icons/64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amilajack/erb-tailwind-example/HEAD/assets/icons/64x64.png -------------------------------------------------------------------------------- /assets/icons/96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amilajack/erb-tailwind-example/HEAD/assets/icons/96x96.png -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["dbaeumer.vscode-eslint", "EditorConfig.EditorConfig"] 3 | } 4 | -------------------------------------------------------------------------------- /assets/icons/1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amilajack/erb-tailwind-example/HEAD/assets/icons/1024x1024.png -------------------------------------------------------------------------------- /assets/icons/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amilajack/erb-tailwind-example/HEAD/assets/icons/128x128.png -------------------------------------------------------------------------------- /assets/icons/256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amilajack/erb-tailwind-example/HEAD/assets/icons/256x256.png -------------------------------------------------------------------------------- /assets/icons/512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amilajack/erb-tailwind-example/HEAD/assets/icons/512x512.png -------------------------------------------------------------------------------- /src/renderer/index.tsx: -------------------------------------------------------------------------------- 1 | import { render } from 'react-dom'; 2 | import App from './App'; 3 | 4 | render(, document.getElementById('root')); 5 | -------------------------------------------------------------------------------- /.github/config.yml: -------------------------------------------------------------------------------- 1 | requiredHeaders: 2 | - Prerequisites 3 | - Expected Behavior 4 | - Current Behavior 5 | - Possible Solution 6 | - Your Environment 7 | -------------------------------------------------------------------------------- /.erb/configs/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-console": "off", 4 | "global-require": "off", 5 | "import/no-dynamic-require": "off" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.erb/configs/webpack.config.eslint.ts: -------------------------------------------------------------------------------- 1 | /* eslint import/no-unresolved: off, import/no-self-import: off */ 2 | 3 | module.exports = require('./webpack.config.renderer.dev').default; 4 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [electron-react-boilerplate, amilajack] 4 | patreon: amilajack 5 | open_collective: electron-react-boilerplate-594 6 | -------------------------------------------------------------------------------- /.erb/configs/postcss.config.js: -------------------------------------------------------------------------------- 1 | const tailwindcss = require('tailwindcss'); 2 | const autoprefixer = require('autoprefixer'); 3 | 4 | module.exports = { 5 | plugins: [tailwindcss, autoprefixer], 6 | }; 7 | -------------------------------------------------------------------------------- /.erb/scripts/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-console": "off", 4 | "global-require": "off", 5 | "import/no-dynamic-require": "off", 6 | "import/no-extraneous-dependencies": "off" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | *.exe binary 3 | *.png binary 4 | *.jpg binary 5 | *.jpeg binary 6 | *.ico binary 7 | *.icns binary 8 | *.eot binary 9 | *.otf binary 10 | *.ttf binary 11 | *.woff binary 12 | *.woff2 binary 13 | -------------------------------------------------------------------------------- /src/__tests__/App.test.tsx: -------------------------------------------------------------------------------- 1 | import '@testing-library/jest-dom'; 2 | import { render } from '@testing-library/react'; 3 | import App from '../renderer/App'; 4 | 5 | describe('App', () => { 6 | it('should render', () => { 7 | expect(render()).toBeTruthy(); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # erb-tailwind-example 2 | 3 | **See the last commit for the required changes for tailwind integration** 4 | 5 | ## Install 6 | 7 | ```bash 8 | git clone --depth 1 --branch main https://github.com/amilajack/erb-tailwind-example.git your-project-name 9 | cd your-project-name 10 | npm install 11 | ``` 12 | -------------------------------------------------------------------------------- /.erb/scripts/link-modules.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import { 3 | appNodeModulesPath, 4 | srcNodeModulesPath, 5 | } from '../configs/webpack.paths'; 6 | 7 | if (!fs.existsSync(srcNodeModulesPath) && fs.existsSync(appNodeModulesPath)) { 8 | fs.symlinkSync(appNodeModulesPath, srcNodeModulesPath, 'junction'); 9 | } 10 | -------------------------------------------------------------------------------- /.erb/scripts/delete-source-maps.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import rimraf from 'rimraf'; 3 | import webpackPaths from '../configs/webpack.paths'; 4 | 5 | export default function deleteSourceMaps() { 6 | rimraf.sync(path.join(webpackPaths.distMainPath, '*.js.map')); 7 | rimraf.sync(path.join(webpackPaths.distRendererPath, '*.js.map')); 8 | } 9 | -------------------------------------------------------------------------------- /release/app/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electron-react-boilerplate", 3 | "version": "4.3.1", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "electron-react-boilerplate", 9 | "version": "4.3.1", 10 | "hasInstallScript": true, 11 | "license": "MIT" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /assets/assets.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint @typescript-eslint/no-explicit-any: off */ 2 | 3 | declare module '*.svg' { 4 | const content: string; 5 | export default content; 6 | } 7 | 8 | declare module '*.png' { 9 | const content: string; 10 | export default content; 11 | } 12 | 13 | declare module '*.jpg' { 14 | const content: string; 15 | export default content; 16 | } 17 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | import colors from 'tailwindcss/colors'; 2 | 3 | module.exports = { 4 | purge: [], 5 | darkMode: false, // or 'media' or 'class' 6 | theme: { 7 | extend: { 8 | colors: { 9 | sky: colors.sky, 10 | cyan: colors.cyan, 11 | }, 12 | }, 13 | }, 14 | variants: { 15 | extend: {}, 16 | }, 17 | plugins: [], 18 | }; 19 | -------------------------------------------------------------------------------- /assets/entitlements.mac.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.cs.allow-unsigned-executable-memory 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/renderer/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello Electron React! 6 | 7 | 8 |
9 | 10 | 18 | 19 | -------------------------------------------------------------------------------- /.erb/scripts/check-node-env.js: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk'; 2 | 3 | export default function checkNodeEnv(expectedEnv) { 4 | if (!expectedEnv) { 5 | throw new Error('"expectedEnv" not set'); 6 | } 7 | 8 | if (process.env.NODE_ENV !== expectedEnv) { 9 | console.log( 10 | chalk.whiteBright.bgRed.bold( 11 | `"process.env.NODE_ENV" must be "${expectedEnv}" to use this webpack config` 12 | ) 13 | ); 14 | process.exit(2); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/3-Feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: You want something added to the boilerplate. 🎉 4 | labels: 'enhancement' 5 | --- 6 | 7 | 16 | -------------------------------------------------------------------------------- /.erb/scripts/clean.js: -------------------------------------------------------------------------------- 1 | import rimraf from 'rimraf'; 2 | import webpackPaths from '../configs/webpack.paths.ts'; 3 | import process from 'process'; 4 | 5 | const args = process.argv.slice(2); 6 | const commandMap = { 7 | dist: webpackPaths.distPath, 8 | release: webpackPaths.releasePath, 9 | dll: webpackPaths.dllPath, 10 | }; 11 | 12 | args.forEach((x) => { 13 | const pathToRemove = commandMap[x]; 14 | if (pathToRemove !== undefined) { 15 | rimraf.sync(pathToRemove); 16 | } 17 | }); 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2-Question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Ask a question.❓ 4 | labels: 'question' 5 | --- 6 | 7 | ## Summary 8 | 9 | 10 | 11 | 20 | -------------------------------------------------------------------------------- /.erb/scripts/check-port-in-use.js: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk'; 2 | import detectPort from 'detect-port'; 3 | 4 | const port = process.env.PORT || '1212'; 5 | 6 | detectPort(port, (err, availablePort) => { 7 | if (port !== String(availablePort)) { 8 | throw new Error( 9 | chalk.whiteBright.bgRed.bold( 10 | `Port "${port}" on "localhost" is already in use. Please use another port. ex: PORT=4343 npm start` 11 | ) 12 | ); 13 | } else { 14 | process.exit(0); 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Coverage directory used by tools like istanbul 11 | coverage 12 | .eslintcache 13 | 14 | # Dependency directory 15 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 16 | node_modules 17 | 18 | # OSX 19 | .DS_Store 20 | 21 | release/app/dist 22 | release/build 23 | .erb/dll 24 | 25 | .idea 26 | npm-debug.log.* 27 | *.css.d.ts 28 | *.sass.d.ts 29 | *.scss.d.ts 30 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Coverage directory used by tools like istanbul 11 | coverage 12 | .eslintcache 13 | 14 | # Dependency directory 15 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 16 | node_modules 17 | 18 | # OSX 19 | .DS_Store 20 | 21 | release/app/dist 22 | release/build 23 | .erb/dll 24 | 25 | .idea 26 | npm-debug.log.* 27 | *.css.d.ts 28 | *.sass.d.ts 29 | *.scss.d.ts 30 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | ".eslintrc": "jsonc", 4 | ".prettierrc": "jsonc", 5 | ".eslintignore": "ignore" 6 | }, 7 | 8 | "javascript.validate.enable": false, 9 | "javascript.format.enable": false, 10 | "typescript.format.enable": false, 11 | 12 | "search.exclude": { 13 | ".git": true, 14 | ".eslintcache": true, 15 | ".erb/dll": true, 16 | "release/{build,app/dist}": true, 17 | "node_modules": true, 18 | "npm-debug.log.*": true, 19 | "test/**/__snapshots__": true, 20 | "yarn.lock": true, 21 | "*.{css,sass,scss}.d.ts": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/util.ts: -------------------------------------------------------------------------------- 1 | /* eslint import/prefer-default-export: off, import/no-mutable-exports: off */ 2 | import { URL } from 'url'; 3 | import path from 'path'; 4 | 5 | export let resolveHtmlPath: (htmlFileName: string) => string; 6 | 7 | if (process.env.NODE_ENV === 'development') { 8 | const port = process.env.PORT || 1212; 9 | resolveHtmlPath = (htmlFileName: string) => { 10 | const url = new URL(`http://localhost:${port}`); 11 | url.pathname = htmlFileName; 12 | return url.href; 13 | }; 14 | } else { 15 | resolveHtmlPath = (htmlFileName: string) => { 16 | return `file://${path.resolve(__dirname, '../renderer/', htmlFileName)}`; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "npm", 6 | "label": "Start Webpack Dev", 7 | "script": "start:renderer", 8 | "options": { 9 | "cwd": "${workspaceFolder}" 10 | }, 11 | "isBackground": true, 12 | "problemMatcher": { 13 | "owner": "custom", 14 | "pattern": { 15 | "regexp": "____________" 16 | }, 17 | "background": { 18 | "activeOnStart": true, 19 | "beginsPattern": "Compiling\\.\\.\\.$", 20 | "endsPattern": "(Compiled successfully|Failed to compile)\\.$" 21 | } 22 | } 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 30 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pr 8 | - discussion 9 | - e2e 10 | - enhancement 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: false 18 | -------------------------------------------------------------------------------- /.erb/scripts/electron-rebuild.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import { execSync } from 'child_process'; 3 | import fs from 'fs'; 4 | import { dependencies } from '../../release/app/package.json'; 5 | import webpackPaths from '../configs/webpack.paths'; 6 | 7 | if ( 8 | Object.keys(dependencies || {}).length > 0 && 9 | fs.existsSync(webpackPaths.appNodeModulesPath) 10 | ) { 11 | const electronRebuildCmd = 12 | '../../node_modules/.bin/electron-rebuild --parallel --force --types prod,dev,optional --module-dir .'; 13 | const cmd = 14 | process.platform === 'win32' 15 | ? electronRebuildCmd.replace(/\//g, '\\') 16 | : electronRebuildCmd; 17 | execSync(cmd, { 18 | cwd: webpackPaths.appPath, 19 | stdio: 'inherit', 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | release: 7 | runs-on: ${{ matrix.os }} 8 | 9 | strategy: 10 | matrix: 11 | os: [macos-latest, windows-latest, ubuntu-latest] 12 | 13 | steps: 14 | - name: Check out Git repository 15 | uses: actions/checkout@v1 16 | 17 | - name: Install Node.js, NPM and Yarn 18 | uses: actions/setup-node@v1 19 | with: 20 | node-version: 15 21 | 22 | - name: npm install 23 | run: | 24 | npm install 25 | 26 | - name: npm test 27 | env: 28 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 29 | run: | 30 | npm run package 31 | npm run lint 32 | npm exec tsc 33 | npm test 34 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Electron: Main", 6 | "type": "node", 7 | "request": "launch", 8 | "protocol": "inspector", 9 | "runtimeExecutable": "npm", 10 | "runtimeArgs": [ 11 | "run start:main --inspect=5858 --remote-debugging-port=9223" 12 | ], 13 | "preLaunchTask": "Start Webpack Dev" 14 | }, 15 | { 16 | "name": "Electron: Renderer", 17 | "type": "chrome", 18 | "request": "attach", 19 | "port": 9223, 20 | "webRoot": "${workspaceFolder}", 21 | "timeout": 15000 22 | } 23 | ], 24 | "compounds": [ 25 | { 26 | "name": "Electron: All", 27 | "configurations": ["Electron: Main", "Electron: Renderer"] 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /.erb/scripts/check-build-exists.ts: -------------------------------------------------------------------------------- 1 | // Check if the renderer and main bundles are built 2 | import path from 'path'; 3 | import chalk from 'chalk'; 4 | import fs from 'fs'; 5 | import webpackPaths from '../configs/webpack.paths'; 6 | 7 | const mainPath = path.join(webpackPaths.distMainPath, 'main.js'); 8 | const rendererPath = path.join(webpackPaths.distRendererPath, 'renderer.js'); 9 | 10 | if (!fs.existsSync(mainPath)) { 11 | throw new Error( 12 | chalk.whiteBright.bgRed.bold( 13 | 'The main process is not built yet. Build it by running "npm run build:main"' 14 | ) 15 | ); 16 | } 17 | 18 | if (!fs.existsSync(rendererPath)) { 19 | throw new Error( 20 | chalk.whiteBright.bgRed.bold( 21 | 'The renderer process is not built yet. Build it by running "npm run build:renderer"' 22 | ) 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/preload.js: -------------------------------------------------------------------------------- 1 | const { contextBridge, ipcRenderer } = require('electron'); 2 | 3 | contextBridge.exposeInMainWorld('electron', { 4 | ipcRenderer: { 5 | myPing() { 6 | ipcRenderer.send('ipc-example', 'ping'); 7 | }, 8 | on(channel, func) { 9 | const validChannels = ['ipc-example']; 10 | if (validChannels.includes(channel)) { 11 | // Deliberately strip event as it includes `sender` 12 | ipcRenderer.on(channel, (event, ...args) => func(...args)); 13 | } 14 | }, 15 | once(channel, func) { 16 | const validChannels = ['ipc-example']; 17 | if (validChannels.includes(channel)) { 18 | // Deliberately strip event as it includes `sender` 19 | ipcRenderer.once(channel, (event, ...args) => func(...args)); 20 | } 21 | }, 22 | }, 23 | }); 24 | -------------------------------------------------------------------------------- /release/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electron-react-boilerplate", 3 | "productName": "electron-react-boilerplate", 4 | "version": "4.3.1", 5 | "description": "Electron application boilerplate based on React, React Router, Webpack, React Hot Loader for rapid application development", 6 | "main": "./dist/main/main.js", 7 | "author": { 8 | "name": "Electron React Boilerplate Maintainers", 9 | "email": "electronreactboilerplate@gmail.com", 10 | "url": "https://github.com/electron-react-boilerplate" 11 | }, 12 | "scripts": { 13 | "electron-rebuild": "node -r ts-node/register ../../.erb/scripts/electron-rebuild.js", 14 | "link-modules": "node -r ts-node/register ../../.erb/scripts/link-modules.js", 15 | "postinstall": "npm run electron-rebuild && npm run link-modules" 16 | }, 17 | "license": "MIT" 18 | } 19 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2021", 4 | "module": "commonjs", 5 | "lib": ["dom", "esnext"], 6 | "declaration": true, 7 | "declarationMap": true, 8 | "jsx": "react-jsx", 9 | "strict": true, 10 | "pretty": true, 11 | "sourceMap": true, 12 | "baseUrl": "./src", 13 | /* Additional Checks */ 14 | "noUnusedLocals": true, 15 | "noUnusedParameters": true, 16 | "noImplicitReturns": true, 17 | "noFallthroughCasesInSwitch": true, 18 | /* Module Resolution Options */ 19 | "moduleResolution": "node", 20 | "esModuleInterop": true, 21 | "allowSyntheticDefaultImports": true, 22 | "resolveJsonModule": true, 23 | "allowJs": true, 24 | "outDir": "release/app/dist" 25 | }, 26 | "exclude": ["test", "release/build", "release/app/dist", ".erb/dll"] 27 | } 28 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: 'erb', 3 | rules: { 4 | // A temporary hack related to IDE not resolving correct package.json 5 | 'import/no-extraneous-dependencies': 'off', 6 | // Since React 17 and typescript 4.1 you can safely disable the rule 7 | 'react/react-in-jsx-scope': 'off', 8 | }, 9 | parserOptions: { 10 | ecmaVersion: 2020, 11 | sourceType: 'module', 12 | project: './tsconfig.json', 13 | tsconfigRootDir: __dirname, 14 | createDefaultProgram: true, 15 | }, 16 | settings: { 17 | 'import/resolver': { 18 | // See https://github.com/benmosher/eslint-plugin-import/issues/1396#issuecomment-575727774 for line below 19 | node: {}, 20 | webpack: { 21 | config: require.resolve('./.erb/configs/webpack.config.eslint.ts'), 22 | }, 23 | }, 24 | 'import/parsers': { 25 | '@typescript-eslint/parser': ['.ts', '.tsx'], 26 | }, 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /.erb/scripts/notarize.js: -------------------------------------------------------------------------------- 1 | const { notarize } = require('electron-notarize'); 2 | const { build } = require('../../package.json'); 3 | 4 | exports.default = async function notarizeMacos(context) { 5 | const { electronPlatformName, appOutDir } = context; 6 | if (electronPlatformName !== 'darwin') { 7 | return; 8 | } 9 | 10 | if (!process.env.CI) { 11 | console.warn('Skipping notarizing step. Packaging is not running in CI'); 12 | return; 13 | } 14 | 15 | if (!('APPLE_ID' in process.env && 'APPLE_ID_PASS' in process.env)) { 16 | console.warn('Skipping notarizing step. APPLE_ID and APPLE_ID_PASS env variables must be set'); 17 | return; 18 | } 19 | 20 | const appName = context.packager.appInfo.productFilename; 21 | 22 | await notarize({ 23 | appBundleId: build.appId, 24 | appPath: `${appOutDir}/${appName}.app`, 25 | appleId: process.env.APPLE_ID, 26 | appleIdPassword: process.env.APPLE_ID_PASS, 27 | }); 28 | }; 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-present Electron React Boilerplate 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 | -------------------------------------------------------------------------------- /.erb/configs/webpack.config.base.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Base webpack config used across other specific configs 3 | */ 4 | 5 | import webpack from 'webpack'; 6 | import webpackPaths from './webpack.paths'; 7 | import { dependencies as externals } from '../../release/app/package.json'; 8 | 9 | export default { 10 | externals: [...Object.keys(externals || {})], 11 | 12 | stats: 'errors-only', 13 | 14 | module: { 15 | rules: [ 16 | { 17 | test: /\.[jt]sx?$/, 18 | exclude: /node_modules/, 19 | use: { 20 | loader: 'ts-loader', 21 | }, 22 | }, 23 | ], 24 | }, 25 | 26 | output: { 27 | path: webpackPaths.srcPath, 28 | // https://github.com/webpack/webpack/issues/1114 29 | library: { 30 | type: 'commonjs2', 31 | }, 32 | }, 33 | 34 | /** 35 | * Determine the array of extensions that should be used to resolve modules. 36 | */ 37 | resolve: { 38 | extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'], 39 | modules: [webpackPaths.srcPath, 'node_modules'], 40 | }, 41 | 42 | plugins: [ 43 | new webpack.EnvironmentPlugin({ 44 | NODE_ENV: 'production', 45 | }), 46 | ], 47 | }; 48 | -------------------------------------------------------------------------------- /.erb/configs/webpack.paths.ts: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const rootPath = path.join(__dirname, '../..'); 4 | 5 | const dllPath = path.join(__dirname, '../dll'); 6 | 7 | const srcPath = path.join(rootPath, 'src'); 8 | const srcMainPath = path.join(srcPath, 'main'); 9 | const srcRendererPath = path.join(srcPath, 'renderer'); 10 | 11 | const releasePath = path.join(rootPath, 'release'); 12 | const appPath = path.join(releasePath, 'app'); 13 | const appPackagePath = path.join(appPath, 'package.json'); 14 | const appNodeModulesPath = path.join(appPath, 'node_modules'); 15 | const srcNodeModulesPath = path.join(srcPath, 'node_modules'); 16 | 17 | const distPath = path.join(appPath, 'dist'); 18 | const distMainPath = path.join(distPath, 'main'); 19 | const distRendererPath = path.join(distPath, 'renderer'); 20 | 21 | const buildPath = path.join(releasePath, 'build'); 22 | 23 | export default { 24 | rootPath, 25 | dllPath, 26 | srcPath, 27 | srcMainPath, 28 | srcRendererPath, 29 | releasePath, 30 | appPath, 31 | appPackagePath, 32 | appNodeModulesPath, 33 | srcNodeModulesPath, 34 | distPath, 35 | distMainPath, 36 | distRendererPath, 37 | buildPath, 38 | }; 39 | -------------------------------------------------------------------------------- /src/renderer/App.css: -------------------------------------------------------------------------------- 1 | /* 2 | * @NOTE: Prepend a `~` to css file paths that are in your node_modules 3 | * See https://github.com/webpack-contrib/sass-loader#imports 4 | */ 5 | body { 6 | position: relative; 7 | color: white; 8 | height: 100vh; 9 | background: linear-gradient( 10 | 200.96deg, 11 | #fedc2a -29.09%, 12 | #dd5789 51.77%, 13 | #7a2c9e 129.35% 14 | ); 15 | font-family: sans-serif; 16 | overflow-y: hidden; 17 | display: flex; 18 | justify-content: center; 19 | align-items: center; 20 | } 21 | 22 | button { 23 | background-color: white; 24 | color: black; 25 | padding: 10px 20px; 26 | border-radius: 10px; 27 | border: none; 28 | appearance: none; 29 | font-size: 1.3rem; 30 | box-shadow: 0px 8px 28px -6px rgba(24, 39, 75, 0.12), 31 | 0px 18px 88px -4px rgba(24, 39, 75, 0.14); 32 | transition: all ease-in 0.1s; 33 | cursor: pointer; 34 | opacity: 0.9; 35 | } 36 | 37 | button:hover { 38 | transform: scale(1.05); 39 | opacity: 1; 40 | } 41 | 42 | li { 43 | list-style: none; 44 | } 45 | 46 | a { 47 | text-decoration: none; 48 | height: fit-content; 49 | width: fit-content; 50 | margin: 10px; 51 | } 52 | 53 | a:hover { 54 | opacity: 1; 55 | text-decoration: none; 56 | } 57 | 58 | .Hello { 59 | display: flex; 60 | justify-content: center; 61 | align-items: center; 62 | margin: 20px 0; 63 | } 64 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | publish: 10 | # To enable auto publishing to github, update your electron publisher 11 | # config in package.json > "build" and remove the conditional below 12 | if: ${{ github.repository_owner == 'electron-react-boilerplate' }} 13 | 14 | runs-on: ${{ matrix.os }} 15 | 16 | strategy: 17 | matrix: 18 | os: [macos-latest] 19 | 20 | steps: 21 | - name: Checkout git repo 22 | uses: actions/checkout@v1 23 | 24 | - name: Install Node, NPM and Yarn 25 | uses: actions/setup-node@v1 26 | with: 27 | node-version: 15 28 | 29 | - name: Install dependencies 30 | run: | 31 | npm install 32 | 33 | - name: Publish releases 34 | env: 35 | # These values are used for auto updates signing 36 | APPLE_ID: ${{ secrets.APPLE_ID }} 37 | APPLE_ID_PASS: ${{ secrets.APPLE_ID_PASS }} 38 | CSC_LINK: ${{ secrets.CSC_LINK }} 39 | CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} 40 | # This is used for uploading release assets to github 41 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 42 | run: | 43 | npm run postinstall 44 | npm run build 45 | npm exec electron-builder -- --publish always --win --mac --linux 46 | -------------------------------------------------------------------------------- /src/renderer/App.tsx: -------------------------------------------------------------------------------- 1 | import { MemoryRouter as Router, Switch, Route } from 'react-router-dom'; 2 | import 'tailwindcss/tailwind.css'; 3 | import icon from '../../assets/icon.svg'; 4 | import './App.css'; 5 | 6 | const Tailwind = () => { 7 | return ( 8 |
9 | ERB + TAILWIND = ❤ 10 |
11 | ); 12 | }; 13 | 14 | const Hello = () => { 15 | return ( 16 |
17 |
18 | icon 19 |
20 |

electron-react-boilerplate

21 | 22 |
23 | 28 | 34 | 35 | 40 | 46 | 47 |
48 |
49 | ); 50 | }; 51 | 52 | export default function App() { 53 | return ( 54 | 55 | 56 | 57 | 58 | 59 | ); 60 | } 61 | -------------------------------------------------------------------------------- /.erb/configs/webpack.config.renderer.dev.dll.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Builds the DLL for development electron renderer process 3 | */ 4 | 5 | import webpack from 'webpack'; 6 | import path from 'path'; 7 | import { merge } from 'webpack-merge'; 8 | import baseConfig from './webpack.config.base'; 9 | import webpackPaths from './webpack.paths'; 10 | import { dependencies } from '../../package.json'; 11 | import checkNodeEnv from '../scripts/check-node-env'; 12 | 13 | checkNodeEnv('development'); 14 | 15 | const dist = webpackPaths.dllPath; 16 | 17 | export default merge(baseConfig, { 18 | context: webpackPaths.rootPath, 19 | 20 | devtool: 'eval', 21 | 22 | mode: 'development', 23 | 24 | target: 'electron-renderer', 25 | 26 | externals: ['fsevents', 'crypto-browserify'], 27 | 28 | /** 29 | * Use `module` from `webpack.config.renderer.dev.js` 30 | */ 31 | module: require('./webpack.config.renderer.dev').default.module, 32 | 33 | entry: { 34 | renderer: Object.keys(dependencies || {}), 35 | }, 36 | 37 | output: { 38 | path: dist, 39 | filename: '[name].dev.dll.js', 40 | library: { 41 | name: 'renderer', 42 | type: 'var', 43 | }, 44 | }, 45 | 46 | plugins: [ 47 | new webpack.DllPlugin({ 48 | path: path.join(dist, '[name].json'), 49 | name: '[name]', 50 | }), 51 | 52 | /** 53 | * Create global constants which can be configured at compile time. 54 | * 55 | * Useful for allowing different behaviour between development builds and 56 | * release builds 57 | * 58 | * NODE_ENV should be production so that modules do not perform certain 59 | * development checks 60 | */ 61 | new webpack.EnvironmentPlugin({ 62 | NODE_ENV: 'development', 63 | }), 64 | 65 | new webpack.LoaderOptionsPlugin({ 66 | debug: true, 67 | options: { 68 | context: webpackPaths.srcPath, 69 | output: { 70 | path: webpackPaths.dllPath, 71 | }, 72 | }, 73 | }), 74 | ], 75 | }); 76 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1-Bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: You're having technical issues. 🐞 4 | labels: 'bug' 5 | --- 6 | 7 | 8 | 9 | ## Prerequisites 10 | 11 | 12 | 13 | - [ ] Using npm 14 | - [ ] Using an up-to-date [`main` branch](https://github.com/electron-react-boilerplate/electron-react-boilerplate/tree/main) 15 | - [ ] Using latest version of devtools. [Check the docs for how to update](https://electron-react-boilerplate.js.org/docs/dev-tools/) 16 | - [ ] Tried solutions mentioned in [#400](https://github.com/electron-react-boilerplate/electron-react-boilerplate/issues/400) 17 | - [ ] For issue in production release, add devtools output of `DEBUG_PROD=true npm run build && npm start` 18 | 19 | ## Expected Behavior 20 | 21 | 22 | 23 | ## Current Behavior 24 | 25 | 26 | 27 | ## Steps to Reproduce 28 | 29 | 30 | 31 | 32 | 1. 33 | 34 | 2. 35 | 36 | 3. 37 | 38 | 4. 39 | 40 | ## Possible Solution (Not obligatory) 41 | 42 | 43 | 44 | ## Context 45 | 46 | 47 | 48 | 49 | 50 | ## Your Environment 51 | 52 | 53 | 54 | - Node version : 55 | - electron-react-boilerplate version or branch : 56 | - Operating System and version : 57 | - Link to your project : 58 | 59 | 68 | -------------------------------------------------------------------------------- /.erb/scripts/check-native-dep.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import chalk from 'chalk'; 3 | import { execSync } from 'child_process'; 4 | import { dependencies } from '../../package.json'; 5 | 6 | if (dependencies) { 7 | const dependenciesKeys = Object.keys(dependencies); 8 | const nativeDeps = fs 9 | .readdirSync('node_modules') 10 | .filter((folder) => fs.existsSync(`node_modules/${folder}/binding.gyp`)); 11 | if (nativeDeps.length === 0) { 12 | process.exit(0); 13 | } 14 | try { 15 | // Find the reason for why the dependency is installed. If it is installed 16 | // because of a devDependency then that is okay. Warn when it is installed 17 | // because of a dependency 18 | const { dependencies: dependenciesObject } = JSON.parse( 19 | execSync(`npm ls ${nativeDeps.join(' ')} --json`).toString() 20 | ); 21 | const rootDependencies = Object.keys(dependenciesObject); 22 | const filteredRootDependencies = rootDependencies.filter((rootDependency) => 23 | dependenciesKeys.includes(rootDependency) 24 | ); 25 | if (filteredRootDependencies.length > 0) { 26 | const plural = filteredRootDependencies.length > 1; 27 | console.log(` 28 | ${chalk.whiteBright.bgYellow.bold( 29 | 'Webpack does not work with native dependencies.' 30 | )} 31 | ${chalk.bold(filteredRootDependencies.join(', '))} ${ 32 | plural ? 'are native dependencies' : 'is a native dependency' 33 | } and should be installed inside of the "./release/app" folder. 34 | First, uninstall the packages from "./package.json": 35 | ${chalk.whiteBright.bgGreen.bold('npm uninstall your-package')} 36 | ${chalk.bold( 37 | 'Then, instead of installing the package to the root "./package.json":' 38 | )} 39 | ${chalk.whiteBright.bgRed.bold('npm install your-package')} 40 | ${chalk.bold('Install the package to "./release/app/package.json"')} 41 | ${chalk.whiteBright.bgGreen.bold('cd ./release/app && npm install your-package')} 42 | Read more about native dependencies at: 43 | ${chalk.bold( 44 | 'https://electron-react-boilerplate.js.org/docs/adding-dependencies/#module-structure' 45 | )} 46 | `); 47 | process.exit(1); 48 | } 49 | } catch (e) { 50 | console.log('Native dependencies could not be checked'); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /.erb/configs/webpack.config.main.prod.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Webpack config for production electron main process 3 | */ 4 | 5 | import path from 'path'; 6 | import webpack from 'webpack'; 7 | import { merge } from 'webpack-merge'; 8 | import TerserPlugin from 'terser-webpack-plugin'; 9 | import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; 10 | import baseConfig from './webpack.config.base'; 11 | import webpackPaths from './webpack.paths'; 12 | import checkNodeEnv from '../scripts/check-node-env'; 13 | import deleteSourceMaps from '../scripts/delete-source-maps'; 14 | 15 | checkNodeEnv('production'); 16 | deleteSourceMaps(); 17 | 18 | const devtoolsConfig = 19 | process.env.DEBUG_PROD === 'true' 20 | ? { 21 | devtool: 'source-map', 22 | } 23 | : {}; 24 | 25 | export default merge(baseConfig, { 26 | ...devtoolsConfig, 27 | 28 | mode: 'production', 29 | 30 | target: 'electron-main', 31 | 32 | entry: { 33 | main: path.join(webpackPaths.srcMainPath, 'main.ts'), 34 | preload: path.join(webpackPaths.srcMainPath, 'preload.js'), 35 | }, 36 | 37 | output: { 38 | path: webpackPaths.distMainPath, 39 | filename: '[name].js', 40 | }, 41 | 42 | optimization: { 43 | minimizer: [ 44 | new TerserPlugin({ 45 | parallel: true, 46 | }), 47 | ], 48 | }, 49 | 50 | plugins: [ 51 | new BundleAnalyzerPlugin({ 52 | analyzerMode: 53 | process.env.OPEN_ANALYZER === 'true' ? 'server' : 'disabled', 54 | openAnalyzer: process.env.OPEN_ANALYZER === 'true', 55 | }), 56 | 57 | /** 58 | * Create global constants which can be configured at compile time. 59 | * 60 | * Useful for allowing different behaviour between development builds and 61 | * release builds 62 | * 63 | * NODE_ENV should be production so that modules do not perform certain 64 | * development checks 65 | */ 66 | new webpack.EnvironmentPlugin({ 67 | NODE_ENV: 'production', 68 | DEBUG_PROD: false, 69 | START_MINIMIZED: false, 70 | }), 71 | ], 72 | 73 | /** 74 | * Disables webpack processing of __dirname and __filename. 75 | * If you run the bundle in node.js it falls back to these values of node.js. 76 | * https://github.com/webpack/webpack/issues/2010 77 | */ 78 | node: { 79 | __dirname: false, 80 | __filename: false, 81 | }, 82 | }); 83 | -------------------------------------------------------------------------------- /assets/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at electronreactboilerplate@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /src/main/main.ts: -------------------------------------------------------------------------------- 1 | /* eslint global-require: off, no-console: off, promise/always-return: off */ 2 | 3 | /** 4 | * This module executes inside of electron's main process. You can start 5 | * electron renderer process from here and communicate with the other processes 6 | * through IPC. 7 | * 8 | * When running `npm run build` or `npm run build:main`, this file is compiled to 9 | * `./src/main.js` using webpack. This gives us some performance wins. 10 | */ 11 | import 'core-js/stable'; 12 | import 'regenerator-runtime/runtime'; 13 | import path from 'path'; 14 | import { app, BrowserWindow, shell, ipcMain } from 'electron'; 15 | import { autoUpdater } from 'electron-updater'; 16 | import log from 'electron-log'; 17 | import MenuBuilder from './menu'; 18 | import { resolveHtmlPath } from './util'; 19 | 20 | export default class AppUpdater { 21 | constructor() { 22 | log.transports.file.level = 'info'; 23 | autoUpdater.logger = log; 24 | autoUpdater.checkForUpdatesAndNotify(); 25 | } 26 | } 27 | 28 | let mainWindow: BrowserWindow | null = null; 29 | 30 | ipcMain.on('ipc-example', async (event, arg) => { 31 | const msgTemplate = (pingPong: string) => `IPC test: ${pingPong}`; 32 | console.log(msgTemplate(arg)); 33 | event.reply('ipc-example', msgTemplate('pong')); 34 | }); 35 | 36 | if (process.env.NODE_ENV === 'production') { 37 | const sourceMapSupport = require('source-map-support'); 38 | sourceMapSupport.install(); 39 | } 40 | 41 | const isDevelopment = 42 | process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true'; 43 | 44 | if (isDevelopment) { 45 | require('electron-debug')(); 46 | } 47 | 48 | const installExtensions = async () => { 49 | const installer = require('electron-devtools-installer'); 50 | const forceDownload = !!process.env.UPGRADE_EXTENSIONS; 51 | const extensions = ['REACT_DEVELOPER_TOOLS']; 52 | 53 | return installer 54 | .default( 55 | extensions.map((name) => installer[name]), 56 | forceDownload 57 | ) 58 | .catch(console.log); 59 | }; 60 | 61 | const createWindow = async () => { 62 | if (isDevelopment) { 63 | await installExtensions(); 64 | } 65 | 66 | const RESOURCES_PATH = app.isPackaged 67 | ? path.join(process.resourcesPath, 'assets') 68 | : path.join(__dirname, '../../assets'); 69 | 70 | const getAssetPath = (...paths: string[]): string => { 71 | return path.join(RESOURCES_PATH, ...paths); 72 | }; 73 | 74 | mainWindow = new BrowserWindow({ 75 | show: false, 76 | width: 1024, 77 | height: 728, 78 | icon: getAssetPath('icon.png'), 79 | webPreferences: { 80 | preload: path.join(__dirname, 'preload.js'), 81 | }, 82 | }); 83 | 84 | mainWindow.loadURL(resolveHtmlPath('index.html')); 85 | 86 | mainWindow.on('ready-to-show', () => { 87 | if (!mainWindow) { 88 | throw new Error('"mainWindow" is not defined'); 89 | } 90 | if (process.env.START_MINIMIZED) { 91 | mainWindow.minimize(); 92 | } else { 93 | mainWindow.show(); 94 | } 95 | }); 96 | 97 | mainWindow.on('closed', () => { 98 | mainWindow = null; 99 | }); 100 | 101 | const menuBuilder = new MenuBuilder(mainWindow); 102 | menuBuilder.buildMenu(); 103 | 104 | // Open urls in the user's browser 105 | mainWindow.webContents.on('new-window', (event, url) => { 106 | event.preventDefault(); 107 | shell.openExternal(url); 108 | }); 109 | 110 | // Remove this if your app does not use auto updates 111 | // eslint-disable-next-line 112 | new AppUpdater(); 113 | }; 114 | 115 | /** 116 | * Add event listeners... 117 | */ 118 | 119 | app.on('window-all-closed', () => { 120 | // Respect the OSX convention of having the application in memory even 121 | // after all windows have been closed 122 | if (process.platform !== 'darwin') { 123 | app.quit(); 124 | } 125 | }); 126 | 127 | app 128 | .whenReady() 129 | .then(() => { 130 | createWindow(); 131 | app.on('activate', () => { 132 | // On macOS it's common to re-create a window in the app when the 133 | // dock icon is clicked and there are no other windows open. 134 | if (mainWindow === null) createWindow(); 135 | }); 136 | }) 137 | .catch(console.log); 138 | -------------------------------------------------------------------------------- /.erb/configs/webpack.config.renderer.prod.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Build config for electron renderer process 3 | */ 4 | 5 | import path from 'path'; 6 | import webpack from 'webpack'; 7 | import HtmlWebpackPlugin from 'html-webpack-plugin'; 8 | import MiniCssExtractPlugin from 'mini-css-extract-plugin'; 9 | import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; 10 | import CssMinimizerPlugin from 'css-minimizer-webpack-plugin'; 11 | import { merge } from 'webpack-merge'; 12 | import TerserPlugin from 'terser-webpack-plugin'; 13 | import baseConfig from './webpack.config.base'; 14 | import webpackPaths from './webpack.paths'; 15 | import checkNodeEnv from '../scripts/check-node-env'; 16 | import deleteSourceMaps from '../scripts/delete-source-maps'; 17 | 18 | checkNodeEnv('production'); 19 | deleteSourceMaps(); 20 | 21 | const devtoolsConfig = 22 | process.env.DEBUG_PROD === 'true' 23 | ? { 24 | devtool: 'source-map', 25 | } 26 | : {}; 27 | 28 | export default merge(baseConfig, { 29 | ...devtoolsConfig, 30 | 31 | mode: 'production', 32 | 33 | target: ['web', 'electron-renderer'], 34 | 35 | entry: [ 36 | 'core-js', 37 | 'regenerator-runtime/runtime', 38 | path.join(webpackPaths.srcRendererPath, 'index.tsx'), 39 | ], 40 | 41 | output: { 42 | path: webpackPaths.distRendererPath, 43 | publicPath: './', 44 | filename: 'renderer.js', 45 | library: { 46 | type: 'umd', 47 | }, 48 | }, 49 | 50 | module: { 51 | rules: [ 52 | { 53 | test: /\.s?(a|c)ss$/, 54 | use: [ 55 | MiniCssExtractPlugin.loader, 56 | { 57 | loader: 'css-loader', 58 | options: { 59 | modules: true, 60 | sourceMap: true, 61 | importLoaders: 1, 62 | }, 63 | }, 64 | 'sass-loader', 65 | { 66 | loader: 'postcss-loader', 67 | options: { 68 | postcssOptions: { 69 | plugins: [require('tailwindcss'), require('autoprefixer')], 70 | }, 71 | }, 72 | }, 73 | ], 74 | include: /\.module\.s?(c|a)ss$/, 75 | }, 76 | { 77 | test: /\.s?(a|c)ss$/, 78 | use: [ 79 | MiniCssExtractPlugin.loader, 80 | 'css-loader', 81 | 'sass-loader', 82 | { 83 | loader: 'postcss-loader', 84 | options: { 85 | postcssOptions: { 86 | plugins: [require('tailwindcss'), require('autoprefixer')], 87 | }, 88 | }, 89 | }, 90 | ], 91 | exclude: /\.module\.s?(c|a)ss$/, 92 | }, 93 | //Font Loader 94 | { 95 | test: /\.(woff|woff2|eot|ttf|otf)$/i, 96 | type: 'asset/resource', 97 | }, 98 | // SVG Font 99 | { 100 | test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, 101 | use: { 102 | loader: 'url-loader', 103 | options: { 104 | limit: 10000, 105 | mimetype: 'image/svg+xml', 106 | }, 107 | }, 108 | }, 109 | // Common Image Formats 110 | { 111 | test: /\.(?:ico|gif|png|jpg|jpeg|webp)$/, 112 | use: 'url-loader', 113 | }, 114 | ], 115 | }, 116 | 117 | optimization: { 118 | minimize: true, 119 | minimizer: [ 120 | new TerserPlugin({ 121 | parallel: true, 122 | }), 123 | new CssMinimizerPlugin(), 124 | ], 125 | }, 126 | 127 | plugins: [ 128 | /** 129 | * Create global constants which can be configured at compile time. 130 | * 131 | * Useful for allowing different behaviour between development builds and 132 | * release builds 133 | * 134 | * NODE_ENV should be production so that modules do not perform certain 135 | * development checks 136 | */ 137 | new webpack.EnvironmentPlugin({ 138 | NODE_ENV: 'production', 139 | DEBUG_PROD: false, 140 | }), 141 | 142 | new MiniCssExtractPlugin({ 143 | filename: 'style.css', 144 | }), 145 | 146 | new BundleAnalyzerPlugin({ 147 | analyzerMode: 148 | process.env.OPEN_ANALYZER === 'true' ? 'server' : 'disabled', 149 | openAnalyzer: process.env.OPEN_ANALYZER === 'true', 150 | }), 151 | 152 | new HtmlWebpackPlugin({ 153 | filename: 'index.html', 154 | template: path.join(webpackPaths.srcRendererPath, 'index.ejs'), 155 | minify: { 156 | collapseWhitespace: true, 157 | removeAttributeQuotes: true, 158 | removeComments: true, 159 | }, 160 | isBrowser: false, 161 | isDevelopment: process.env.NODE_ENV !== 'production', 162 | }), 163 | ], 164 | }); 165 | -------------------------------------------------------------------------------- /.erb/configs/webpack.config.renderer.dev.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import fs from 'fs'; 3 | import webpack from 'webpack'; 4 | import HtmlWebpackPlugin from 'html-webpack-plugin'; 5 | import chalk from 'chalk'; 6 | import { merge } from 'webpack-merge'; 7 | import { spawn, execSync } from 'child_process'; 8 | import baseConfig from './webpack.config.base'; 9 | import webpackPaths from './webpack.paths'; 10 | import checkNodeEnv from '../scripts/check-node-env'; 11 | import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin'; 12 | 13 | // When an ESLint server is running, we can't set the NODE_ENV so we'll check if it's 14 | // at the dev webpack config is not accidentally run in a production environment 15 | if (process.env.NODE_ENV === 'production') { 16 | checkNodeEnv('development'); 17 | } 18 | 19 | const port = process.env.PORT || 1212; 20 | const manifest = path.resolve(webpackPaths.dllPath, 'renderer.json'); 21 | const requiredByDLLConfig = module.parent.filename.includes( 22 | 'webpack.config.renderer.dev.dll' 23 | ); 24 | 25 | /** 26 | * Warn if the DLL is not built 27 | */ 28 | if ( 29 | !requiredByDLLConfig && 30 | !(fs.existsSync(webpackPaths.dllPath) && fs.existsSync(manifest)) 31 | ) { 32 | console.log( 33 | chalk.black.bgYellow.bold( 34 | 'The DLL files are missing. Sit back while we build them for you with "npm run build-dll"' 35 | ) 36 | ); 37 | execSync('npm run postinstall'); 38 | } 39 | 40 | export default merge(baseConfig, { 41 | devtool: 'inline-source-map', 42 | 43 | mode: 'development', 44 | 45 | target: ['web', 'electron-renderer'], 46 | 47 | entry: [ 48 | `webpack-dev-server/client?http://localhost:${port}/dist`, 49 | 'webpack/hot/only-dev-server', 50 | 'core-js', 51 | 'regenerator-runtime/runtime', 52 | path.join(webpackPaths.srcRendererPath, 'index.tsx'), 53 | ], 54 | 55 | output: { 56 | path: webpackPaths.distRendererPath, 57 | publicPath: '/', 58 | filename: 'renderer.dev.js', 59 | library: { 60 | type: 'umd', 61 | }, 62 | }, 63 | 64 | module: { 65 | rules: [ 66 | { 67 | test: /\.s?css$/, 68 | use: [ 69 | 'style-loader', 70 | { 71 | loader: 'css-loader', 72 | options: { 73 | modules: true, 74 | sourceMap: true, 75 | importLoaders: 1, 76 | }, 77 | }, 78 | 'sass-loader', 79 | { 80 | loader: 'postcss-loader', 81 | options: { 82 | postcssOptions: { 83 | plugins: [require('tailwindcss'), require('autoprefixer')], 84 | }, 85 | }, 86 | }, 87 | ], 88 | include: /\.module\.s?(c|a)ss$/, 89 | }, 90 | { 91 | test: /\.s?css$/, 92 | use: [ 93 | 'style-loader', 94 | 'css-loader', 95 | 'sass-loader', 96 | { 97 | loader: 'postcss-loader', 98 | options: { 99 | postcssOptions: { 100 | plugins: [require('tailwindcss'), require('autoprefixer')], 101 | }, 102 | }, 103 | }, 104 | ], 105 | exclude: /\.module\.s?(c|a)ss$/, 106 | }, 107 | //Font Loader 108 | { 109 | test: /\.(woff|woff2|eot|ttf|otf)$/i, 110 | type: 'asset/resource', 111 | }, 112 | // SVG Font 113 | { 114 | test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, 115 | use: { 116 | loader: 'url-loader', 117 | options: { 118 | limit: 10000, 119 | mimetype: 'image/svg+xml', 120 | }, 121 | }, 122 | }, 123 | // Common Image Formats 124 | { 125 | test: /\.(?:ico|gif|png|jpg|jpeg|webp)$/, 126 | use: 'url-loader', 127 | }, 128 | ], 129 | }, 130 | plugins: [ 131 | requiredByDLLConfig 132 | ? null 133 | : new webpack.DllReferencePlugin({ 134 | context: webpackPaths.dllPath, 135 | manifest: require(manifest), 136 | sourceType: 'var', 137 | }), 138 | 139 | new webpack.NoEmitOnErrorsPlugin(), 140 | 141 | /** 142 | * Create global constants which can be configured at compile time. 143 | * 144 | * Useful for allowing different behaviour between development builds and 145 | * release builds 146 | * 147 | * NODE_ENV should be production so that modules do not perform certain 148 | * development checks 149 | * 150 | * By default, use 'development' as NODE_ENV. This can be overriden with 151 | * 'staging', for example, by changing the ENV variables in the npm scripts 152 | */ 153 | new webpack.EnvironmentPlugin({ 154 | NODE_ENV: 'development', 155 | }), 156 | 157 | new webpack.LoaderOptionsPlugin({ 158 | debug: true, 159 | }), 160 | 161 | new ReactRefreshWebpackPlugin(), 162 | 163 | new HtmlWebpackPlugin({ 164 | filename: path.join('index.html'), 165 | template: path.join(webpackPaths.srcRendererPath, 'index.ejs'), 166 | minify: { 167 | collapseWhitespace: true, 168 | removeAttributeQuotes: true, 169 | removeComments: true, 170 | }, 171 | isBrowser: false, 172 | env: process.env.NODE_ENV, 173 | isDevelopment: process.env.NODE_ENV !== 'production', 174 | nodeModules: webpackPaths.appNodeModulesPath, 175 | }), 176 | ], 177 | 178 | node: { 179 | __dirname: false, 180 | __filename: false, 181 | }, 182 | 183 | devServer: { 184 | port, 185 | compress: true, 186 | hot: true, 187 | headers: { 'Access-Control-Allow-Origin': '*' }, 188 | static: { 189 | publicPath: '/', 190 | }, 191 | historyApiFallback: { 192 | verbose: true, 193 | disableDotRule: false, 194 | }, 195 | onBeforeSetupMiddleware() { 196 | console.log('Starting Main Process...'); 197 | spawn('npm', ['run', 'start:main'], { 198 | shell: true, 199 | env: process.env, 200 | stdio: 'inherit', 201 | }) 202 | .on('close', (code) => process.exit(code)) 203 | .on('error', (spawnError) => console.error(spawnError)); 204 | }, 205 | }, 206 | }); 207 | -------------------------------------------------------------------------------- /src/main/menu.ts: -------------------------------------------------------------------------------- 1 | import { 2 | app, 3 | Menu, 4 | shell, 5 | BrowserWindow, 6 | MenuItemConstructorOptions, 7 | } from 'electron'; 8 | 9 | interface DarwinMenuItemConstructorOptions extends MenuItemConstructorOptions { 10 | selector?: string; 11 | submenu?: DarwinMenuItemConstructorOptions[] | Menu; 12 | } 13 | 14 | export default class MenuBuilder { 15 | mainWindow: BrowserWindow; 16 | 17 | constructor(mainWindow: BrowserWindow) { 18 | this.mainWindow = mainWindow; 19 | } 20 | 21 | buildMenu(): Menu { 22 | if ( 23 | process.env.NODE_ENV === 'development' || 24 | process.env.DEBUG_PROD === 'true' 25 | ) { 26 | this.setupDevelopmentEnvironment(); 27 | } 28 | 29 | const template = 30 | process.platform === 'darwin' 31 | ? this.buildDarwinTemplate() 32 | : this.buildDefaultTemplate(); 33 | 34 | const menu = Menu.buildFromTemplate(template); 35 | Menu.setApplicationMenu(menu); 36 | 37 | return menu; 38 | } 39 | 40 | setupDevelopmentEnvironment(): void { 41 | this.mainWindow.webContents.on('context-menu', (_, props) => { 42 | const { x, y } = props; 43 | 44 | Menu.buildFromTemplate([ 45 | { 46 | label: 'Inspect element', 47 | click: () => { 48 | this.mainWindow.webContents.inspectElement(x, y); 49 | }, 50 | }, 51 | ]).popup({ window: this.mainWindow }); 52 | }); 53 | } 54 | 55 | buildDarwinTemplate(): MenuItemConstructorOptions[] { 56 | const subMenuAbout: DarwinMenuItemConstructorOptions = { 57 | label: 'Electron', 58 | submenu: [ 59 | { 60 | label: 'About ElectronReact', 61 | selector: 'orderFrontStandardAboutPanel:', 62 | }, 63 | { type: 'separator' }, 64 | { label: 'Services', submenu: [] }, 65 | { type: 'separator' }, 66 | { 67 | label: 'Hide ElectronReact', 68 | accelerator: 'Command+H', 69 | selector: 'hide:', 70 | }, 71 | { 72 | label: 'Hide Others', 73 | accelerator: 'Command+Shift+H', 74 | selector: 'hideOtherApplications:', 75 | }, 76 | { label: 'Show All', selector: 'unhideAllApplications:' }, 77 | { type: 'separator' }, 78 | { 79 | label: 'Quit', 80 | accelerator: 'Command+Q', 81 | click: () => { 82 | app.quit(); 83 | }, 84 | }, 85 | ], 86 | }; 87 | const subMenuEdit: DarwinMenuItemConstructorOptions = { 88 | label: 'Edit', 89 | submenu: [ 90 | { label: 'Undo', accelerator: 'Command+Z', selector: 'undo:' }, 91 | { label: 'Redo', accelerator: 'Shift+Command+Z', selector: 'redo:' }, 92 | { type: 'separator' }, 93 | { label: 'Cut', accelerator: 'Command+X', selector: 'cut:' }, 94 | { label: 'Copy', accelerator: 'Command+C', selector: 'copy:' }, 95 | { label: 'Paste', accelerator: 'Command+V', selector: 'paste:' }, 96 | { 97 | label: 'Select All', 98 | accelerator: 'Command+A', 99 | selector: 'selectAll:', 100 | }, 101 | ], 102 | }; 103 | const subMenuViewDev: MenuItemConstructorOptions = { 104 | label: 'View', 105 | submenu: [ 106 | { 107 | label: 'Reload', 108 | accelerator: 'Command+R', 109 | click: () => { 110 | this.mainWindow.webContents.reload(); 111 | }, 112 | }, 113 | { 114 | label: 'Toggle Full Screen', 115 | accelerator: 'Ctrl+Command+F', 116 | click: () => { 117 | this.mainWindow.setFullScreen(!this.mainWindow.isFullScreen()); 118 | }, 119 | }, 120 | { 121 | label: 'Toggle Developer Tools', 122 | accelerator: 'Alt+Command+I', 123 | click: () => { 124 | this.mainWindow.webContents.toggleDevTools(); 125 | }, 126 | }, 127 | ], 128 | }; 129 | const subMenuViewProd: MenuItemConstructorOptions = { 130 | label: 'View', 131 | submenu: [ 132 | { 133 | label: 'Toggle Full Screen', 134 | accelerator: 'Ctrl+Command+F', 135 | click: () => { 136 | this.mainWindow.setFullScreen(!this.mainWindow.isFullScreen()); 137 | }, 138 | }, 139 | ], 140 | }; 141 | const subMenuWindow: DarwinMenuItemConstructorOptions = { 142 | label: 'Window', 143 | submenu: [ 144 | { 145 | label: 'Minimize', 146 | accelerator: 'Command+M', 147 | selector: 'performMiniaturize:', 148 | }, 149 | { label: 'Close', accelerator: 'Command+W', selector: 'performClose:' }, 150 | { type: 'separator' }, 151 | { label: 'Bring All to Front', selector: 'arrangeInFront:' }, 152 | ], 153 | }; 154 | const subMenuHelp: MenuItemConstructorOptions = { 155 | label: 'Help', 156 | submenu: [ 157 | { 158 | label: 'Learn More', 159 | click() { 160 | shell.openExternal('https://electronjs.org'); 161 | }, 162 | }, 163 | { 164 | label: 'Documentation', 165 | click() { 166 | shell.openExternal( 167 | 'https://github.com/electron/electron/tree/main/docs#readme' 168 | ); 169 | }, 170 | }, 171 | { 172 | label: 'Community Discussions', 173 | click() { 174 | shell.openExternal('https://www.electronjs.org/community'); 175 | }, 176 | }, 177 | { 178 | label: 'Search Issues', 179 | click() { 180 | shell.openExternal('https://github.com/electron/electron/issues'); 181 | }, 182 | }, 183 | ], 184 | }; 185 | 186 | const subMenuView = 187 | process.env.NODE_ENV === 'development' || 188 | process.env.DEBUG_PROD === 'true' 189 | ? subMenuViewDev 190 | : subMenuViewProd; 191 | 192 | return [subMenuAbout, subMenuEdit, subMenuView, subMenuWindow, subMenuHelp]; 193 | } 194 | 195 | buildDefaultTemplate() { 196 | const templateDefault = [ 197 | { 198 | label: '&File', 199 | submenu: [ 200 | { 201 | label: '&Open', 202 | accelerator: 'Ctrl+O', 203 | }, 204 | { 205 | label: '&Close', 206 | accelerator: 'Ctrl+W', 207 | click: () => { 208 | this.mainWindow.close(); 209 | }, 210 | }, 211 | ], 212 | }, 213 | { 214 | label: '&View', 215 | submenu: 216 | process.env.NODE_ENV === 'development' || 217 | process.env.DEBUG_PROD === 'true' 218 | ? [ 219 | { 220 | label: '&Reload', 221 | accelerator: 'Ctrl+R', 222 | click: () => { 223 | this.mainWindow.webContents.reload(); 224 | }, 225 | }, 226 | { 227 | label: 'Toggle &Full Screen', 228 | accelerator: 'F11', 229 | click: () => { 230 | this.mainWindow.setFullScreen( 231 | !this.mainWindow.isFullScreen() 232 | ); 233 | }, 234 | }, 235 | { 236 | label: 'Toggle &Developer Tools', 237 | accelerator: 'Alt+Ctrl+I', 238 | click: () => { 239 | this.mainWindow.webContents.toggleDevTools(); 240 | }, 241 | }, 242 | ] 243 | : [ 244 | { 245 | label: 'Toggle &Full Screen', 246 | accelerator: 'F11', 247 | click: () => { 248 | this.mainWindow.setFullScreen( 249 | !this.mainWindow.isFullScreen() 250 | ); 251 | }, 252 | }, 253 | ], 254 | }, 255 | { 256 | label: 'Help', 257 | submenu: [ 258 | { 259 | label: 'Learn More', 260 | click() { 261 | shell.openExternal('https://electronjs.org'); 262 | }, 263 | }, 264 | { 265 | label: 'Documentation', 266 | click() { 267 | shell.openExternal( 268 | 'https://github.com/electron/electron/tree/main/docs#readme' 269 | ); 270 | }, 271 | }, 272 | { 273 | label: 'Community Discussions', 274 | click() { 275 | shell.openExternal('https://www.electronjs.org/community'); 276 | }, 277 | }, 278 | { 279 | label: 'Search Issues', 280 | click() { 281 | shell.openExternal('https://github.com/electron/electron/issues'); 282 | }, 283 | }, 284 | ], 285 | }, 286 | ]; 287 | 288 | return templateDefault; 289 | } 290 | } 291 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electron-react-boilerplate", 3 | "productName": "ElectronReact", 4 | "description": "Electron application boilerplate based on React, React Router, Webpack, React Fast Refresh for rapid application development", 5 | "scripts": { 6 | "build": "concurrently \"npm run build:main\" \"npm run build:renderer\"", 7 | "build:main": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.main.prod.ts", 8 | "build:renderer": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.prod.ts", 9 | "rebuild": "electron-rebuild --parallel --types prod,dev,optional --module-dir src", 10 | "lint": "cross-env NODE_ENV=development eslint . --cache --ext .js,.jsx,.ts,.tsx", 11 | "package": "ts-node ./.erb/scripts/clean.js dist && npm run build && electron-builder build --publish never", 12 | "postinstall": "ts-node .erb/scripts/check-native-dep.js && electron-builder install-app-deps && cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.dev.dll.ts && opencollective-postinstall", 13 | "start": "ts-node ./.erb/scripts/check-port-in-use.js && npm run start:renderer", 14 | "start:main": "cross-env NODE_ENV=development electron -r ts-node/register/transpile-only ./src/main/main.ts", 15 | "start:renderer": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack serve --config ./.erb/configs/webpack.config.renderer.dev.ts", 16 | "test": "jest" 17 | }, 18 | "lint-staged": { 19 | "*.{js,jsx,ts,tsx}": [ 20 | "cross-env NODE_ENV=development eslint --cache" 21 | ], 22 | "*.json,.{eslintrc,prettierrc}": [ 23 | "prettier --ignore-path .eslintignore --parser json --write" 24 | ], 25 | "*.{css,scss}": [ 26 | "prettier --ignore-path .eslintignore --single-quote --write" 27 | ], 28 | "*.{html,md,yml}": [ 29 | "prettier --ignore-path .eslintignore --single-quote --write" 30 | ] 31 | }, 32 | "build": { 33 | "productName": "ElectronReact", 34 | "appId": "org.erb.ElectronReact", 35 | "asar": true, 36 | "asarUnpack": "**\\*.{node,dll}", 37 | "files": [ 38 | "dist", 39 | "node_modules", 40 | "package.json" 41 | ], 42 | "afterSign": ".erb/scripts/notarize.js", 43 | "mac": { 44 | "target": { 45 | "target": "default", 46 | "arch": [ 47 | "arm64", 48 | "x64" 49 | ] 50 | }, 51 | "type": "distribution", 52 | "hardenedRuntime": true, 53 | "entitlements": "assets/entitlements.mac.plist", 54 | "entitlementsInherit": "assets/entitlements.mac.plist", 55 | "gatekeeperAssess": false 56 | }, 57 | "dmg": { 58 | "contents": [ 59 | { 60 | "x": 130, 61 | "y": 220 62 | }, 63 | { 64 | "x": 410, 65 | "y": 220, 66 | "type": "link", 67 | "path": "/Applications" 68 | } 69 | ] 70 | }, 71 | "win": { 72 | "target": [ 73 | "nsis" 74 | ] 75 | }, 76 | "linux": { 77 | "target": [ 78 | "AppImage" 79 | ], 80 | "category": "Development" 81 | }, 82 | "directories": { 83 | "app": "release/app", 84 | "buildResources": "assets", 85 | "output": "release/build" 86 | }, 87 | "extraResources": [ 88 | "./assets/**" 89 | ], 90 | "publish": { 91 | "provider": "github", 92 | "owner": "electron-react-boilerplate", 93 | "repo": "electron-react-boilerplate" 94 | } 95 | }, 96 | "repository": { 97 | "type": "git", 98 | "url": "git+https://github.com/electron-react-boilerplate/electron-react-boilerplate.git" 99 | }, 100 | "author": { 101 | "name": "Electron React Boilerplate Maintainers", 102 | "email": "electronreactboilerplate@gmail.com", 103 | "url": "https://electron-react-boilerplate.js.org" 104 | }, 105 | "contributors": [ 106 | { 107 | "name": "Amila Welihinda", 108 | "email": "amilajack@gmail.com", 109 | "url": "https://github.com/amilajack" 110 | }, 111 | { 112 | "name": "John Tran", 113 | "email": "jptran318@gmail.com", 114 | "url": "https://github.com/jooohhn" 115 | } 116 | ], 117 | "license": "MIT", 118 | "bugs": { 119 | "url": "https://github.com/electron-react-boilerplate/electron-react-boilerplate/issues" 120 | }, 121 | "keywords": [ 122 | "electron", 123 | "boilerplate", 124 | "react", 125 | "typescript", 126 | "ts", 127 | "sass", 128 | "webpack", 129 | "hot", 130 | "reload" 131 | ], 132 | "homepage": "https://github.com/electron-react-boilerplate/electron-react-boilerplate#readme", 133 | "jest": { 134 | "testURL": "http://localhost/", 135 | "testEnvironment": "jsdom", 136 | "transform": { 137 | "\\.(ts|tsx|js|jsx)$": "ts-jest" 138 | }, 139 | "moduleNameMapper": { 140 | "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/.erb/mocks/fileMock.js", 141 | "\\.(css|less|sass|scss)$": "identity-obj-proxy" 142 | }, 143 | "moduleFileExtensions": [ 144 | "js", 145 | "jsx", 146 | "ts", 147 | "tsx", 148 | "json" 149 | ], 150 | "moduleDirectories": [ 151 | "node_modules", 152 | "release/app/node_modules" 153 | ], 154 | "testPathIgnorePatterns": [ 155 | "release/app/dist" 156 | ], 157 | "setupFiles": [ 158 | "./.erb/scripts/check-build-exists.ts" 159 | ] 160 | }, 161 | "devDependencies": { 162 | "@pmmmwh/react-refresh-webpack-plugin": "0.5.1", 163 | "@teamsupercell/typings-for-css-modules-loader": "^2.5.1", 164 | "@testing-library/jest-dom": "^5.14.1", 165 | "@testing-library/react": "^12.1.2", 166 | "@types/enzyme": "^3.10.10", 167 | "@types/enzyme-adapter-react-16": "^1.0.6", 168 | "@types/history": "4.7.9", 169 | "@types/jest": "^27.0.2", 170 | "@types/node": "16.11.6", 171 | "@types/react": "^17.0.33", 172 | "@types/react-dom": "^17.0.10", 173 | "@types/react-router": "^5.1.17", 174 | "@types/react-router-dom": "^5.3.2", 175 | "@types/react-test-renderer": "^17.0.1", 176 | "@types/terser-webpack-plugin": "^5.0.4", 177 | "@types/webpack-env": "^1.16.3", 178 | "@typescript-eslint/eslint-plugin": "^5.2.0", 179 | "autoprefixer": "^10.4.0", 180 | "browserslist-config-erb": "^0.0.3", 181 | "chalk": "^4.1.2", 182 | "concurrently": "^6.3.0", 183 | "core-js": "^3.19.0", 184 | "cross-env": "^7.0.3", 185 | "css-loader": "^6.5.0", 186 | "css-minimizer-webpack-plugin": "^3.1.1", 187 | "detect-port": "^1.3.0", 188 | "electron": "^15.3.0", 189 | "electron-builder": "^22.13.1", 190 | "electron-devtools-installer": "^3.2.0", 191 | "electron-notarize": "^1.1.1", 192 | "electron-rebuild": "^3.2.3", 193 | "enzyme": "^3.11.0", 194 | "enzyme-adapter-react-16": "^1.15.6", 195 | "enzyme-to-json": "^3.6.2", 196 | "eslint": "^7.32.0", 197 | "eslint-config-airbnb-base": "^14.2.1", 198 | "eslint-config-erb": "^4.0.3", 199 | "eslint-plugin-compat": "^3.13.0", 200 | "eslint-plugin-import": "^2.25.2", 201 | "eslint-plugin-jest": "^25.2.2", 202 | "eslint-plugin-jsx-a11y": "^6.4.1", 203 | "eslint-plugin-promise": "^5.1.1", 204 | "eslint-plugin-react": "^7.26.1", 205 | "eslint-plugin-react-hooks": "^4.2.0", 206 | "file-loader": "^6.2.0", 207 | "html-webpack-plugin": "^5.5.0", 208 | "husky": "7.0.4", 209 | "identity-obj-proxy": "^3.0.0", 210 | "jest": "^27.3.1", 211 | "lint-staged": "^11.2.6", 212 | "mini-css-extract-plugin": "^2.4.3", 213 | "opencollective-postinstall": "^2.0.3", 214 | "postcss": "^8.3.11", 215 | "postcss-loader": "^6.2.0", 216 | "prettier": "^2.4.1", 217 | "react-refresh": "^0.10.0", 218 | "react-refresh-typescript": "^2.0.2", 219 | "react-test-renderer": "^17.0.2", 220 | "rimraf": "^3.0.2", 221 | "sass": "^1.43.4", 222 | "sass-loader": "^12.3.0", 223 | "style-loader": "^3.3.1", 224 | "tailwindcss": "^2.2.19", 225 | "terser-webpack-plugin": "^5.2.4", 226 | "ts-jest": "^27.0.7", 227 | "ts-loader": "^9.2.6", 228 | "ts-node": "^10.4.0", 229 | "typescript": "^4.4.4", 230 | "url-loader": "^4.1.1", 231 | "webpack": "^5.60.0", 232 | "webpack-bundle-analyzer": "^4.5.0", 233 | "webpack-cli": "^4.9.1", 234 | "webpack-dev-server": "^4.4.0", 235 | "webpack-merge": "^5.8.0" 236 | }, 237 | "dependencies": { 238 | "electron-debug": "^3.2.0", 239 | "electron-log": "^4.4.1", 240 | "electron-updater": "^4.3.9", 241 | "history": "4.x.x", 242 | "react": "^17.0.2", 243 | "react-dom": "^17.0.2", 244 | "react-router-dom": "^5.3.0", 245 | "regenerator-runtime": "^0.13.9" 246 | }, 247 | "devEngines": { 248 | "node": ">=14.x", 249 | "npm": ">=7.x" 250 | }, 251 | "collective": { 252 | "url": "https://opencollective.com/electron-react-boilerplate-594" 253 | }, 254 | "browserslist": [], 255 | "prettier": { 256 | "overrides": [ 257 | { 258 | "files": [ 259 | ".prettierrc", 260 | ".eslintrc" 261 | ], 262 | "options": { 263 | "parser": "json" 264 | } 265 | } 266 | ], 267 | "singleQuote": true 268 | }, 269 | "husky": { 270 | "hooks": { 271 | "pre-commit": "lint-staged" 272 | } 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 2.1.0 2 | 3 | - Migrate to `css-minifier-webpack-plugin` 4 | 5 | # 2.0.1 6 | 7 | ## Fixes 8 | 9 | - Fix broken css linking in production build 10 | 11 | # 2.0.0 12 | 13 | ## Breaking Changes 14 | 15 | - drop redux 16 | - remove counter example app 17 | - simplify directory structure 18 | - move `dll` dir to `.erb` dir 19 | - fix icon/font import paths 20 | - migrate to `react-refresh` from `react-hot-loader` 21 | - migrate to webpack@5 22 | - migrate to electron@11 23 | - remove e2e tests and testcafe integration 24 | - rename `app` dir to more conventional `src` dir 25 | - rename `resources` dir to `assets` 26 | - simplify npm scripts 27 | - drop stylelint 28 | - simplify styling of boilerplate app 29 | - remove `START_HOT` env variable 30 | - notarize support 31 | - landing page boilerplate 32 | - docs updates 33 | - restore removed debugging support 34 | 35 | # 1.4.0 36 | 37 | - Migrate to `eslint-config-erb@2` 38 | - Rename `dev` npm script to `start` 39 | - GitHub Actions: only publish GitHub releases when on master branch 40 | 41 | # 1.3.1 42 | 43 | - Fix sass building bug ([#2540](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/2540)) 44 | - Fix CI bug related to E2E tests and network timeouts 45 | - Move automated dependency PRs to `next` ([#2554](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/2554)) 46 | - Bump dependencies to patch semver 47 | 48 | # 1.3.0 49 | 50 | - Fixes E2E tests ([#2516](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/2516)) 51 | - Fixes preload entrypoint ([#2503](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/2503)) 52 | - Downgrade to `electron@8` 53 | - Bump dependencies to latest semver 54 | 55 | # 1.2.0 56 | 57 | - Migrate to redux toolkit 58 | - Lazy load routes with react suspense 59 | - Drop support for azure-pipelines and use only github actions 60 | - Bump all deps to latest semver 61 | - Remove `test-e2e` script from tests (blocked on release of https://github.com/DevExpress/testcafe-browser-provider-electron/pull/65) 62 | - Swap `typed-css-modules-webpack-plugin` for `typings-for-css-modules-loader` 63 | - Use latest version of `eslint-config-erb` 64 | - Remove unnecessary file extensions from ts exclude 65 | - Add experimental support for vscode debugging 66 | - Revert https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/2365 as default for users, provide as opt in option 67 | 68 | # 1.1.0 69 | 70 | - Fix #2402 71 | - Simplify configs (https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/2406) 72 | 73 | # 1.0.0 74 | 75 | - Migrate to TypeScript from Flow ([#2363](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/2363)) 76 | - Use browserslist for `@babel/preset-env` targets ([#2368](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/2368)) 77 | - Use preload script, disable `nodeIntegration` in renderer process for [improved security](https://www.electronjs.org/docs/tutorial/security#2-do-not-enable-nodejs-integration-for-remote-content) ([#2365](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/2365)) 78 | - Add support for azure pipelines ([#2369](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/2369)) 79 | - Disable sourcemaps in production 80 | 81 | # 0.18.1 (2019.12.12) 82 | 83 | - Fix HMR env bug ([#2343](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/2343)) 84 | - Bump all deps to latest semver 85 | - Bump to `electron@7` 86 | 87 | # 0.18.0 (2019.11.19) 88 | 89 | - Bump electron to `electron@6` (`electron@7` introduces breaking changes to testcafe end to end tests) 90 | - Revert back to [two `package.json` structure](https://www.electron.build/tutorials/two-package-structure) 91 | - Bump all deps to latest semver 92 | 93 | # 0.17.1 (2018.11.20) 94 | 95 | - Fix `yarn test-e2e` and testcafe for single package.json structure 96 | - Fixes incorrect path in `yarn start` script 97 | - Bumped deps 98 | - Bump g++ in travis 99 | - Change clone arguments to clone only master 100 | - Change babel config to target current electron version 101 | 102 | For full change list, see https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/2021 103 | 104 | # 0.17.0 (2018.10.30) 105 | 106 | - upgraded to `babel@7` (thanks to @vikr01 🎉🎉🎉) 107 | - migrated from [two `package.json` structure](https://www.electron.build/tutorials/two-package-structure) (thanks to @HyperSprite!) 108 | - initial auto update support (experimental) 109 | - migrate from greenkeeper to [renovate](https://renovatebot.com) 110 | - added issue template 111 | - use `babel-preset-env` to target current electron version 112 | - add [opencollective](https://opencollective.com/electron-react-boilerplate-594) banner message display in postinstall script (help support ERB 🙏) 113 | - fix failing ci issues 114 | 115 | # 0.16.0 (2018.10.3) 116 | 117 | - removed unused dependencies 118 | - migrate from `react-redux-router` to `connect-react-router` 119 | - move webpack configs to `./webpack` dir 120 | - use `g++` on travis when testing linux 121 | - migrate from `spectron` to `testcafe` for e2e tests 122 | - add linting support for config styles 123 | - changed stylelint config 124 | - temporarily disabled flow in appveyor to make ci pass 125 | - added necessary infra to publish releases from ci 126 | 127 | # 0.15.0 (2018.8.25) 128 | 129 | - Performance: cache webpack uglify results 130 | - Feature: add start minimized feature 131 | - Feature: lint and fix styles with prettier and stylelint 132 | - Feature: add greenkeeper support 133 | 134 | # 0.14.0 (2018.5.24) 135 | 136 | - Improved CI timings 137 | - Migrated README commands to yarn from npm 138 | - Improved vscode config 139 | - Updated all dependencies to latest semver 140 | - Fix `electron-rebuild` script bug 141 | - Migrated to `mini-css-extract-plugin` from `extract-text-plugin` 142 | - Added `optimize-css-assets-webpack-plugin` 143 | - Run `prettier` on json, css, scss, and more filetypes 144 | 145 | # 0.13.3 (2018.5.24) 146 | 147 | - Add git precommit hook, when git commit will use `prettier` to format git add code 148 | - Add format code function in `lint-fix` npm script which can use `prettier` to format project js code 149 | 150 | # 0.13.2 (2018.1.31) 151 | 152 | - Hot Module Reload (HMR) fixes 153 | - Bumped all dependencies to latest semver 154 | - Prevent error propagation of `CheckNativeDeps` script 155 | 156 | # 0.13.1 (2018.1.13) 157 | 158 | - Hot Module Reload (HMR) fixes 159 | - Bumped all dependencies to latest semver 160 | - Fixed electron-rebuild script 161 | - Fixed tests scripts to run on all platforms 162 | - Skip redux logs in console in test ENV 163 | 164 | # 0.13.0 (2018.1.6) 165 | 166 | #### Additions 167 | 168 | - Add native dependencies check on postinstall 169 | - Updated all dependencies to latest semver 170 | 171 | # 0.12.0 (2017.7.8) 172 | 173 | #### Misc 174 | 175 | - Removed `babel-polyfill` 176 | - Renamed and alphabetized npm scripts 177 | 178 | #### Breaking 179 | 180 | - Changed node dev `__dirname` and `__filename` to node built in fn's (https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/1035) 181 | - Renamed `src/bundle.js` to `src/renderer.prod.js` for consistency 182 | - Renamed `dll/vendor.js` to `dll/renderer.dev.dll.js` for consistency 183 | 184 | #### Additions 185 | 186 | - Enable node_modules cache on CI 187 | 188 | # 0.11.2 (2017.5.1) 189 | 190 | Yay! Another patch release. This release mostly includes refactorings and router bug fixes. Huge thanks to @anthonyraymond! 191 | 192 | ⚠️ Windows electron builds are failing because of [this issue](https://github.com/electron/electron/issues/9321). This is not an issue with the boilerplate ⚠️ 193 | 194 | #### Breaking 195 | 196 | - **Renamed `./src/main.development.js` => `./src/main.{dev,prod}.js`:** [#963](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/963) 197 | 198 | #### Fixes 199 | 200 | - **Fixed reloading when not on `/` path:** [#958](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/958) [#949](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/949) 201 | 202 | #### Additions 203 | 204 | - **Added support for stylefmt:** [#960](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/960) 205 | 206 | # 0.11.1 (2017.4.23) 207 | 208 | You can now debug the production build with devtools like so: 209 | 210 | ``` 211 | DEBUG_PROD=true npm run package 212 | ``` 213 | 214 | 🎉🎉🎉 215 | 216 | #### Additions 217 | 218 | - **Added support for debugging production build:** [#fab245a](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/941/commits/fab245a077d02a09630f74270806c0c534a4ff95) 219 | 220 | #### Bug Fixes 221 | 222 | - **Fixed bug related to importing native dependencies:** [#933](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/933) 223 | 224 | #### Improvements 225 | 226 | - **Updated all deps to latest semver** 227 | 228 | # 0.11.0 (2017.4.19) 229 | 230 | Here's the most notable changes since `v0.10.0`. Its been about a year since a release has been pushed. Expect a new release to be published every 3-4 weeks. 231 | 232 | #### Breaking Changes 233 | 234 | - **Dropped support for node < 6** 235 | - **Refactored webpack config files** 236 | - **Migrate to two-package.json project structure** 237 | - **Updated all devDeps to latest semver** 238 | - **Migrated to Jest:** [#768](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/768) 239 | - **Migrated to `react-router@4`** 240 | - **Migrated to `electron-builder@4`** 241 | - **Migrated to `webpack@2`** 242 | - **Migrated to `react-hot-loader@3`** 243 | - **Changed default live reload server PORT to `1212` from `3000`** 244 | 245 | #### Additions 246 | 247 | - **Added support for Yarn:** [#451](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/451) 248 | - **Added support for Flow:** [#425](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/425) 249 | - **Added support for stylelint:** [#911](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/911) 250 | - **Added support for electron-builder:** [#876](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/876) 251 | - **Added optional support for SASS:** [#880](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/880) 252 | - **Added support for eslint-plugin-flowtype:** [#911](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/911) 253 | - **Added support for appveyor:** [#280](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/280) 254 | - **Added support for webpack dlls:** [#860](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/860) 255 | - **Route based code splitting:** [#884](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/884) 256 | - **Added support for Webpack Bundle Analyzer:** [#922](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/922) 257 | 258 | #### Improvements 259 | 260 | - **Parallelize renderer and main build processes when running `npm run build`** 261 | - **Dynamically generate electron app menu** 262 | - **Improved vscode integration:** [#856](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/856) 263 | 264 | #### Bug Fixes 265 | 266 | - **Fixed hot module replacement race condition bug:** [#917](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/917) [#920](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/920) 267 | 268 | # 0.10.0 (2016.4.18) 269 | 270 | #### Improvements 271 | 272 | - **Use Babel in main process with Webpack build:** [#201](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/201) 273 | - **Change targets to built-in support by webpack:** [#197](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/197) 274 | - **use es2015 syntax for webpack configs:** [#195](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/195) 275 | - **Open application when webcontent is loaded:** [#192](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/192) 276 | - **Upgraded dependencies** 277 | 278 | #### Bug fixed 279 | 280 | - **Fix `npm list electron-prebuilt` in package.js:** [#188](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/188) 281 | 282 | # 0.9.0 (2016.3.23) 283 | 284 | #### Improvements 285 | 286 | - **Added [redux-logger](https://github.com/fcomb/redux-logger)** 287 | - **Upgraded [react-router-redux](https://github.com/reactjs/react-router-redux) to v4** 288 | - **Upgraded dependencies** 289 | - **Added `npm run dev` command:** [#162](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/162) 290 | - **electron to v0.37.2** 291 | 292 | #### Breaking Changes 293 | 294 | - **css module as default:** [#154](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/154). 295 | - **set default NODE_ENV to production:** [#140](https://github.com/electron-react-boilerplate/electron-react-boilerplate/issues/140) 296 | 297 | # 0.8.0 (2016.2.17) 298 | 299 | #### Bug fixed 300 | 301 | - **Fix lint errors** 302 | - **Fix Webpack publicPath for production builds**: [#119](https://github.com/electron-react-boilerplate/electron-react-boilerplate/issues/119). 303 | - **package script now chooses correct OS icon extension** 304 | 305 | #### Improvements 306 | 307 | - **babel 6** 308 | - **Upgrade Dependencies** 309 | - **Enable CSS source maps** 310 | - **Add json-loader**: [#128](https://github.com/electron-react-boilerplate/electron-react-boilerplate/issues/128). 311 | - **react-router 2.0 and react-router-redux 3.0** 312 | 313 | # 0.7.1 (2015.12.27) 314 | 315 | #### Bug fixed 316 | 317 | - **Fixed npm script on windows 10:** [#103](https://github.com/electron-react-boilerplate/electron-react-boilerplate/issues/103). 318 | - **history and react-router version bump**: [#109](https://github.com/electron-react-boilerplate/electron-react-boilerplate/issues/109), [#110](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/110). 319 | 320 | #### Improvements 321 | 322 | - **electron 0.36** 323 | 324 | # 0.7.0 (2015.12.16) 325 | 326 | #### Bug fixed 327 | 328 | - **Fixed process.env.NODE_ENV variable in webpack:** [#74](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/74). 329 | - **add missing object-assign**: [#76](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/76). 330 | - **packaging in npm@3:** [#77](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/77). 331 | - **compatibility in windows:** [#100](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/100). 332 | - **disable chrome debugger in production env:** [#102](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/102). 333 | 334 | #### Improvements 335 | 336 | - **redux** 337 | - **css-modules** 338 | - **upgrade to react-router 1.x** 339 | - **unit tests** 340 | - **e2e tests** 341 | - **travis-ci** 342 | - **upgrade to electron 0.35.x** 343 | - **use es2015** 344 | - **check dev engine for node and npm** 345 | 346 | # 0.6.5 (2015.11.7) 347 | 348 | #### Improvements 349 | 350 | - **Bump style-loader to 0.13** 351 | - **Bump css-loader to 0.22** 352 | 353 | # 0.6.4 (2015.10.27) 354 | 355 | #### Improvements 356 | 357 | - **Bump electron-debug to 0.3** 358 | 359 | # 0.6.3 (2015.10.26) 360 | 361 | #### Improvements 362 | 363 | - **Initialize ExtractTextPlugin once:** [#64](https://github.com/electron-react-boilerplate/electron-react-boilerplate/issues/64). 364 | 365 | # 0.6.2 (2015.10.18) 366 | 367 | #### Bug fixed 368 | 369 | - **Babel plugins production env not be set properly:** [#57](https://github.com/electron-react-boilerplate/electron-react-boilerplate/issues/57). 370 | 371 | # 0.6.1 (2015.10.17) 372 | 373 | #### Improvements 374 | 375 | - **Bump electron to v0.34.0** 376 | 377 | # 0.6.0 (2015.10.16) 378 | 379 | #### Breaking Changes 380 | 381 | - **From react-hot-loader to react-transform** 382 | 383 | # 0.5.2 (2015.10.15) 384 | 385 | #### Improvements 386 | 387 | - **Run tests with babel-register:** [#29](https://github.com/electron-react-boilerplate/electron-react-boilerplate/issues/29). 388 | 389 | # 0.5.1 (2015.10.12) 390 | 391 | #### Bug fixed 392 | 393 | - **Fix #51:** use `path.join(__dirname` instead of `./`. 394 | 395 | # 0.5.0 (2015.10.11) 396 | 397 | #### Improvements 398 | 399 | - **Simplify webpack config** see [#50](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/50). 400 | 401 | #### Breaking Changes 402 | 403 | - **webpack configs** 404 | - **port changed:** changed default port from 2992 to 3000. 405 | - **npm scripts:** remove `start-dev` and `dev-server`. rename `hot-dev-server` to `hot-server`. 406 | 407 | # 0.4.3 (2015.9.22) 408 | 409 | #### Bug fixed 410 | 411 | - **Fix #45 zeromq crash:** bump version of `electron-prebuilt`. 412 | 413 | # 0.4.2 (2015.9.15) 414 | 415 | #### Bug fixed 416 | 417 | - **run start-hot breaks chrome refresh(CTRL+R) (#42)**: bump `electron-debug` to `0.2.1` 418 | 419 | # 0.4.1 (2015.9.11) 420 | 421 | #### Improvements 422 | 423 | - **use electron-prebuilt version for packaging (#33)** 424 | 425 | # 0.4.0 (2015.9.5) 426 | 427 | #### Improvements 428 | 429 | - **update dependencies** 430 | 431 | # 0.3.0 (2015.8.31) 432 | 433 | #### Improvements 434 | 435 | - **eslint-config-airbnb** 436 | 437 | # 0.2.10 (2015.8.27) 438 | 439 | #### Features 440 | 441 | - **custom placeholder icon** 442 | 443 | #### Improvements 444 | 445 | - **electron-renderer as target:** via [webpack-target-electron-renderer](https://github.com/chentsulin/webpack-target-electron-renderer) 446 | 447 | # 0.2.9 (2015.8.18) 448 | 449 | #### Bug fixed 450 | 451 | - **Fix hot-reload** 452 | 453 | # 0.2.8 (2015.8.13) 454 | 455 | #### Improvements 456 | 457 | - **bump electron-debug** 458 | - **babelrc** 459 | - **organize webpack scripts** 460 | 461 | # 0.2.7 (2015.7.9) 462 | 463 | #### Bug fixed 464 | 465 | - **defaultProps:** fix typos. 466 | 467 | # 0.2.6 (2015.7.3) 468 | 469 | #### Features 470 | 471 | - **menu** 472 | 473 | #### Bug fixed 474 | 475 | - **package.js:** include webpack build. 476 | 477 | # 0.2.5 (2015.7.1) 478 | 479 | #### Features 480 | 481 | - **NPM Script:** support multi-platform 482 | - **package:** `--all` option 483 | 484 | # 0.2.4 (2015.6.9) 485 | 486 | #### Bug fixed 487 | 488 | - **Eslint:** typo, [#17](https://github.com/electron-react-boilerplate/electron-react-boilerplate/issues/17) and improve `.eslintrc` 489 | 490 | # 0.2.3 (2015.6.3) 491 | 492 | #### Features 493 | 494 | - **Package Version:** use latest release electron version as default 495 | - **Ignore Large peerDependencies** 496 | 497 | #### Bug fixed 498 | 499 | - **Npm Script:** typo, [#6](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/6) 500 | - **Missing css:** [#7](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/7) 501 | 502 | # 0.2.2 (2015.6.2) 503 | 504 | #### Features 505 | 506 | - **electron-debug** 507 | 508 | #### Bug fixed 509 | 510 | - **Webpack:** add `.json` and `.node` to extensions for imitating node require. 511 | - **Webpack:** set `node_modules` to externals for native module support. 512 | 513 | # 0.2.1 (2015.5.30) 514 | 515 | #### Bug fixed 516 | 517 | - **Webpack:** #1, change build target to `atom`. 518 | 519 | # 0.2.0 (2015.5.30) 520 | 521 | #### Features 522 | 523 | - **Ignore:** `test`, `tools`, `release` folder and devDependencies in `package.json`. 524 | - **Support asar** 525 | - **Support icon** 526 | 527 | # 0.1.0 (2015.5.27) 528 | 529 | #### Features 530 | 531 | - **Webpack:** babel, react-hot, ... 532 | - **Flux:** actions, api, components, containers, stores.. 533 | - **Package:** darwin (osx), linux and win32 (windows) platform. 534 | --------------------------------------------------------------------------------