├── .gitignore ├── LICENSE ├── README.md ├── app ├── index.html ├── index.js ├── scripts │ ├── app.jsx │ └── components │ │ └── main.jsx └── styles │ └── main.scss ├── gulpfile.js ├── images └── term.png └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### OSX template 3 | .DS_Store 4 | .AppleDouble 5 | .LSOverride 6 | 7 | # Icon must end with two \r 8 | Icon 9 | 10 | # Thumbnails 11 | ._* 12 | 13 | # Files that might appear in the root of a volume 14 | .DocumentRevisions-V100 15 | .fseventsd 16 | .Spotlight-V100 17 | .TemporaryItems 18 | .Trashes 19 | .VolumeIcon.icns 20 | 21 | # Directories potentially created on remote AFP share 22 | .AppleDB 23 | .AppleDesktop 24 | Network Trash Folder 25 | Temporary Items 26 | .apdisk 27 | 28 | 29 | ### Vim template 30 | [._]*.s[a-w][a-z] 31 | [._]s[a-w][a-z] 32 | *.un~ 33 | Session.vim 34 | .netrwhist 35 | *~ 36 | 37 | 38 | ### Windows template 39 | # Windows image file caches 40 | Thumbs.db 41 | ehthumbs.db 42 | 43 | # Folder config file 44 | Desktop.ini 45 | 46 | # Recycle Bin used on file shares 47 | $RECYCLE.BIN/ 48 | 49 | # Windows Installer files 50 | *.cab 51 | *.msi 52 | *.msm 53 | *.msp 54 | 55 | # Windows shortcuts 56 | *.lnk 57 | 58 | 59 | ### JetBrains template 60 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 61 | 62 | *.iml 63 | 64 | ## Directory-based project format: 65 | .idea/ 66 | # if you remove the above rule, at least ignore the following: 67 | 68 | # User-specific stuff: 69 | # .idea/workspace.xml 70 | # .idea/tasks.xml 71 | # .idea/dictionaries 72 | 73 | # Sensitive or high-churn files: 74 | # .idea/dataSources.ids 75 | # .idea/dataSources.xml 76 | # .idea/sqlDataSources.xml 77 | # .idea/dynamic.xml 78 | # .idea/uiDesigner.xml 79 | 80 | # Gradle: 81 | # .idea/gradle.xml 82 | # .idea/libraries 83 | 84 | # Mongo Explorer plugin: 85 | # .idea/mongoSettings.xml 86 | 87 | ## File-based project format: 88 | *.ipr 89 | *.iws 90 | 91 | ## Plugin-specific files: 92 | 93 | # IntelliJ 94 | /out/ 95 | 96 | # mpeltonen/sbt-idea plugin 97 | .idea_modules/ 98 | 99 | # JIRA plugin 100 | atlassian-ide-plugin.xml 101 | 102 | # Crashlytics plugin (for Android Studio and IntelliJ) 103 | com_crashlytics_export_strings.xml 104 | crashlytics.properties 105 | crashlytics-build.properties 106 | 107 | 108 | 109 | ### Yeoman template 110 | node_modules/ 111 | bower_components/ 112 | *.log 113 | 114 | build/ 115 | dist/ 116 | 117 | 118 | ### Node template 119 | # Logs 120 | logs 121 | *.log 122 | 123 | # Runtime data 124 | pids 125 | *.pid 126 | *.seed 127 | 128 | # Directory for instrumented libs generated by jscoverage/JSCover 129 | lib-cov 130 | 131 | # Coverage directory used by tools like istanbul 132 | coverage 133 | 134 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 135 | .grunt 136 | 137 | # node-waf configuration 138 | .lock-wscript 139 | 140 | # Compiled binary addons (http://nodejs.org/api/addons.html) 141 | build/Release 142 | 143 | # Dependency directory 144 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 145 | node_modules 146 | 147 | 148 | ### electron-starterify 149 | release/ 150 | cache/ 151 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Jaewe Heo 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ANOTHER *[EPP][epp](Electron aPPlication)* 2 | 3 | 4 | # electron-starterify 5 | 6 | :electric_plug: [Electron][electron] application skeleton based on [React][react] 7 | 8 | 9 | ## Usage 10 | 11 | Install dependencies. 12 | 13 | ```sh 14 | $ npm install 15 | ``` 16 | 17 | ### Development 18 | 19 | ```sh 20 | $ gulp watch 21 | ``` 22 | 23 | ### Release (Deploy) 24 | 25 | 1. Set `release` [task option][opt] in `gulpfile.js` if you want. 26 | - Check [latest version of electron][latest] 27 | 28 | 2. Run 29 | ```sh 30 | $ gulp build 31 | ``` 32 | 33 | 3. See `./release` directory 34 | 35 | 36 | ## Troubleshooting 37 | 38 | - [Error: spawn zip ENOENT][issue1] on Windows 39 | 40 | 41 | [electron]: http://electron.atom.io/ 42 | [react]: http://facebook.github.io/react/ 43 | [latest]: https://github.com/atom/electron/releases/latest 44 | [opt]: https://github.com/mainyaa/gulp-electron#options 45 | [issue1]: https://github.com/importre/electron-starterify/issues/1#issuecomment-101391136 46 | [epp]: https://github.com/importre/epp/ 47 | -------------------------------------------------------------------------------- /app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | electron-starterify 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const app = require('app'); 4 | const BrowserWindow = require('browser-window'); 5 | const Menu = require('menu'); 6 | const MenuItem = require('menu-item'); 7 | 8 | // report crashes to the Electron project 9 | require('crash-reporter').start(); 10 | 11 | // prevent window being GC'd 12 | let mainWindow = null; 13 | var menu = null; 14 | 15 | app.on('window-all-closed', function () { 16 | app.quit(); 17 | }); 18 | 19 | app.on('ready', function () { 20 | mainWindow = new BrowserWindow({ 21 | width: 1280, 22 | height: 768, 23 | resizable: true 24 | }); 25 | 26 | mainWindow.loadUrl(`file://${__dirname}/index.html`); 27 | 28 | try { 29 | var bs = require("browser-sync").create(); 30 | bs.watch(`${__dirname}/**/*`, function (event, file) { 31 | if (event == "change" && file.match(/(.css|.html|.js)$/g)) { 32 | mainWindow.reloadIgnoringCache(); 33 | } 34 | }); 35 | } catch (e) { 36 | } 37 | 38 | if (process.platform == 'darwin') { 39 | var darwinTmpl = [ 40 | { 41 | label: 'Electron', 42 | submenu: [ 43 | { 44 | label: 'About Electron', 45 | selector: 'orderFrontStandardAboutPanel:' 46 | }, 47 | { 48 | type: 'separator' 49 | }, 50 | { 51 | label: 'Services', 52 | submenu: [] 53 | }, 54 | { 55 | type: 'separator' 56 | }, 57 | { 58 | label: 'Hide Electron', 59 | accelerator: 'Command+H', 60 | selector: 'hide:' 61 | }, 62 | { 63 | label: 'Hide Others', 64 | accelerator: 'Command+Shift+H', 65 | selector: 'hideOtherApplications:' 66 | }, 67 | { 68 | label: 'Show All', 69 | selector: 'unhideAllApplications:' 70 | }, 71 | { 72 | type: 'separator' 73 | }, 74 | { 75 | label: 'Quit', 76 | accelerator: 'Command+Q', 77 | click: function () { 78 | app.quit(); 79 | } 80 | } 81 | ] 82 | }, 83 | { 84 | label: 'Edit', 85 | submenu: [ 86 | { 87 | label: 'Undo', 88 | accelerator: 'Command+Z', 89 | selector: 'undo:' 90 | }, 91 | { 92 | label: 'Redo', 93 | accelerator: 'Shift+Command+Z', 94 | selector: 'redo:' 95 | }, 96 | { 97 | type: 'separator' 98 | }, 99 | { 100 | label: 'Cut', 101 | accelerator: 'Command+X', 102 | selector: 'cut:' 103 | }, 104 | { 105 | label: 'Copy', 106 | accelerator: 'Command+C', 107 | selector: 'copy:' 108 | }, 109 | { 110 | label: 'Paste', 111 | accelerator: 'Command+V', 112 | selector: 'paste:' 113 | }, 114 | { 115 | label: 'Select All', 116 | accelerator: 'Command+A', 117 | selector: 'selectAll:' 118 | } 119 | ] 120 | }, 121 | { 122 | label: 'View', 123 | submenu: [ 124 | { 125 | label: 'Reload', 126 | accelerator: 'Command+R', 127 | click: function () { 128 | mainWindow.restart(); 129 | } 130 | }, 131 | { 132 | label: 'Toggle Full Screen', 133 | accelerator: 'Ctrl+Command+F', 134 | click: function () { 135 | mainWindow.setFullScreen(!mainWindow.isFullScreen()); 136 | } 137 | }, 138 | { 139 | label: 'Toggle Developer Tools', 140 | accelerator: 'Alt+Command+I', 141 | click: function () { 142 | mainWindow.toggleDevTools(); 143 | } 144 | } 145 | ] 146 | }, 147 | { 148 | label: 'Window', 149 | submenu: [ 150 | { 151 | label: 'Minimize', 152 | accelerator: 'Command+M', 153 | selector: 'performMiniaturize:' 154 | }, 155 | { 156 | label: 'Close', 157 | accelerator: 'Command+W', 158 | selector: 'performClose:' 159 | }, 160 | { 161 | type: 'separator' 162 | }, 163 | { 164 | label: 'Bring All to Front', 165 | selector: 'arrangeInFront:' 166 | } 167 | ] 168 | }, 169 | { 170 | label: 'Help', 171 | submenu: [ 172 | { 173 | label: 'Learn More', 174 | click: function () { 175 | require('shell').openExternal('http://electron.atom.io') 176 | } 177 | }, 178 | { 179 | label: 'Documentation', 180 | click: function () { 181 | require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') 182 | } 183 | }, 184 | { 185 | label: 'Community Discussions', 186 | click: function () { 187 | require('shell').openExternal('https://discuss.atom.io/c/electron') 188 | } 189 | }, 190 | { 191 | label: 'Search Issues', 192 | click: function () { 193 | require('shell').openExternal('https://github.com/atom/electron/issues') 194 | } 195 | } 196 | ] 197 | } 198 | ]; 199 | 200 | menu = Menu.buildFromTemplate(darwinTmpl); 201 | Menu.setApplicationMenu(menu); 202 | } else { 203 | var template = [ 204 | { 205 | label: '&File', 206 | submenu: [ 207 | { 208 | label: '&Open', 209 | accelerator: 'Ctrl+O' 210 | }, 211 | { 212 | label: '&Close', 213 | accelerator: 'Ctrl+W', 214 | click: function () { 215 | mainWindow.close(); 216 | } 217 | } 218 | ] 219 | }, 220 | { 221 | label: '&View', 222 | submenu: [ 223 | { 224 | label: '&Reload', 225 | accelerator: 'Ctrl+R', 226 | click: function () { 227 | mainWindow.restart(); 228 | } 229 | }, 230 | { 231 | label: 'Toggle &Full Screen', 232 | accelerator: 'F11', 233 | click: function () { 234 | mainWindow.setFullScreen(!mainWindow.isFullScreen()); 235 | } 236 | }, 237 | { 238 | label: 'Toggle &Developer Tools', 239 | accelerator: 'Alt+Ctrl+I', 240 | click: function () { 241 | mainWindow.toggleDevTools(); 242 | } 243 | } 244 | ] 245 | }, 246 | { 247 | label: 'Help', 248 | submenu: [ 249 | { 250 | label: 'Learn More', 251 | click: function () { 252 | require('shell').openExternal('http://electron.atom.io') 253 | } 254 | }, 255 | { 256 | label: 'Documentation', 257 | click: function () { 258 | require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') 259 | } 260 | }, 261 | { 262 | label: 'Community Discussions', 263 | click: function () { 264 | require('shell').openExternal('https://discuss.atom.io/c/electron') 265 | } 266 | }, 267 | { 268 | label: 'Search Issues', 269 | click: function () { 270 | require('shell').openExternal('https://github.com/atom/electron/issues') 271 | } 272 | } 273 | ] 274 | } 275 | ]; 276 | 277 | menu = Menu.buildFromTemplate(template); 278 | mainWindow.setMenu(menu); 279 | } 280 | 281 | 282 | mainWindow.on('closed', function () { 283 | // deref the window 284 | // for multiple windows store them in an array 285 | mainWindow = null; 286 | }); 287 | }); 288 | -------------------------------------------------------------------------------- /app/scripts/app.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Main from './components/main.jsx' 3 | 4 | window.React = React; 5 | 6 | React.render(
, document.body); 7 | -------------------------------------------------------------------------------- /app/scripts/components/main.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | let Main = React.createClass({ 4 | render: function () { 5 | return ( 6 |
7 |

electron-starterify

8 | Hello, Electron!!! 9 |
10 | ) 11 | } 12 | }); 13 | 14 | export default Main; 15 | -------------------------------------------------------------------------------- /app/styles/main.scss: -------------------------------------------------------------------------------- 1 | *, *:before, *:after { 2 | box-sizing: border-box; 3 | } 4 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var babelify = require('babelify'); 4 | var browserSync = require('browser-sync'); 5 | var browserify = require('browserify'); 6 | var buffer = require('vinyl-buffer'); 7 | var changed = require('gulp-changed'); 8 | var copy = require('gulp-copy'); 9 | var csso = require('gulp-csso'); 10 | var del = require('del'); 11 | var electron = require('gulp-electron'); 12 | var gulp = require('gulp'); 13 | var notify = require('gulp-notify'); 14 | var packageJson = require('./package.json'); 15 | var sass = require('gulp-sass'); 16 | var shell = require('gulp-shell'); 17 | var source = require('vinyl-source-stream'); 18 | var uglify = require('gulp-uglify'); 19 | 20 | var o = { 21 | jsx: 'app/scripts/app.jsx', 22 | scss: 'app/styles/main.scss', 23 | bundle: 'app.js', 24 | distJs: 'dist/app/js', 25 | distCss: 'dist/app/css' 26 | }; 27 | 28 | gulp.task('clean', function (cb) { 29 | del(['dist', 'release'], cb); 30 | }); 31 | 32 | gulp.task('images', function () { 33 | return gulp.src('images/**/*') 34 | .pipe(gulp.dest('dist/app/images')); 35 | }); 36 | 37 | gulp.task('etc', function () { 38 | return gulp.src(['app/index.html', 'app/index.js', 'package.json']) 39 | .pipe(gulp.dest('dist/app')); 40 | }); 41 | 42 | gulp.task('copy', function () { 43 | gulp.start(['images', 'etc']); 44 | }); 45 | 46 | gulp.task('browserify', function () { 47 | return browserify(o.jsx) 48 | .transform(babelify) 49 | .bundle() 50 | .pipe(source(o.bundle)) 51 | .pipe(buffer()) 52 | .pipe(uglify()) 53 | .pipe(gulp.dest(o.distJs)); 54 | }); 55 | 56 | gulp.task('browserifyDev', function () { 57 | return browserify(o.jsx) 58 | .transform(babelify) 59 | .bundle() 60 | .pipe(source(o.bundle)) 61 | .pipe(gulp.dest(o.distJs)); 62 | }); 63 | 64 | gulp.task('styles', function () { 65 | return gulp.src(o.scss) 66 | .pipe(changed(o.distCss)) 67 | .pipe(sass({errLogToConsole: true})) 68 | .on('error', notify.onError()) 69 | .pipe(csso()) 70 | .pipe(gulp.dest(o.distCss)); 71 | }); 72 | 73 | gulp.task('browserSync', function () { 74 | var bs = browserSync.create(); 75 | bs.watch('app/**/*').on('change', function () { 76 | gulp.start(['browserifyDev', 'copy', 'styles']); 77 | }); 78 | }); 79 | 80 | gulp.task('electron', ['browserifyDev'], function () { 81 | var cmd = ''; 82 | switch (process.platform) { 83 | case 'darwin': 84 | cmd = './node_modules/electron-prebuilt/dist/Electron.app/Contents/MacOS/Electron dist/app'; 85 | break; 86 | case 'win32': 87 | cmd = 'node_modules\\electron-prebuilt\\dist\\electron.exe dist\\app'; 88 | break; 89 | case 'linux': 90 | cmd = './node_modules/electron-prebuilt/dist/electron dist/app'; 91 | break; 92 | default: 93 | console.log(process.platform + ' is not supported.'); 94 | return; 95 | } 96 | 97 | return gulp.src('', {read: false}) 98 | .pipe(shell(cmd)); 99 | }); 100 | 101 | gulp.task('release', ['browserify'], function () { 102 | gulp.src('') 103 | .pipe(electron({ 104 | src: './dist/app', 105 | packageJson: packageJson, 106 | release: './release', 107 | cache: './cache', 108 | version: 'v0.26.0', 109 | rebuild: false, 110 | platforms: ['win32-ia32', 'darwin-x64'] 111 | })) 112 | .pipe(gulp.dest('')); 113 | }); 114 | 115 | gulp.task('watch', ['clean'], function () { 116 | gulp.start(['browserifyDev', 'copy', 'styles', 'browserSync', 'electron']); 117 | }); 118 | 119 | gulp.task('build', ['clean'], function () { 120 | process.env.NODE_ENV = 'production'; 121 | gulp.start(['browserify', 'copy', 'styles', 'release']); 122 | }); 123 | 124 | gulp.task('default', function () { 125 | console.log('Run `gulp watch` or `gulp build`'); 126 | }); 127 | 128 | -------------------------------------------------------------------------------- /images/term.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/importre/electron-starterify/4edbc88f517b4ffae6738ea51e75c45ab487a698/images/term.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electron-starterify", 3 | "version": "0.0.1", 4 | "description": "Electron application skeleton based on React", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/importre/electron-starterify.git" 12 | }, 13 | "keywords": [ 14 | "electron", 15 | "react" 16 | ], 17 | "author": "Jaewe Heo", 18 | "license": "BSD", 19 | "bugs": { 20 | "url": "https://github.com/importre/electron-starterify/issues" 21 | }, 22 | "homepage": "https://github.com/importre/electron-starterify#readme", 23 | "dependencies": { 24 | "react": "^0.13.3", 25 | "superagent": "^1.2.0" 26 | }, 27 | "devDependencies": { 28 | "asar": "^0.6.1", 29 | "babelify": "^6.1.0", 30 | "browser-sync": "^2.7.1", 31 | "browserify": "^10.1.3", 32 | "del": "^1.1.1", 33 | "electron-prebuilt": "^0.25.3-2", 34 | "gulp": "^3.8.11", 35 | "gulp-changed": "^1.2.1", 36 | "gulp-copy": "0.0.2", 37 | "gulp-csso": "^1.0.0", 38 | "gulp-electron": "0.0.3", 39 | "gulp-notify": "^2.2.0", 40 | "gulp-sass": "^2.0.0", 41 | "gulp-shell": "^0.4.1", 42 | "gulp-uglify": "^1.2.0", 43 | "vinyl-buffer": "^1.0.0", 44 | "vinyl-source-stream": "^1.1.0" 45 | } 46 | } 47 | --------------------------------------------------------------------------------