Skip to content

Instantly share code, notes, and snippets.

@geta6
Last active November 30, 2015 07:35
Show Gist options
  • Save geta6/6cde69cd40ffb917d2e6 to your computer and use it in GitHub Desktop.
Save geta6/6cde69cd40ffb917d2e6 to your computer and use it in GitHub Desktop.
{
"stage": 0
}
build/**
release/**
node_modules/**
{
"extends": "airbnb",
"parser": "babel-eslint",
"env": {
"mocha": true
},
"rules": {
"object-curly-spacing": [2, "never"],
"jsx-quotes": [2, "prefer-single"],
"space-before-function-paren": 0,
"id-length": 0,
"no-new": 0,
"no-else-return": 0,
"no-loop-func": 0,
"no-unused-expressions": 0,
"no-const-assign": 2,
"react/display-name": 2,
"react/jsx-boolean-value": 0
},
"globals": {
"__DEV__": true
}
}
import os from 'os';
import cp from 'child_process';
import path from 'path';
import gulp from 'gulp';
import util from 'gulp-util';
import chalk from 'chalk';
import packager from 'electron-packager';
import ncp from 'ncp';
import gaze from 'gaze';
import del from 'del';
import run from 'run-sequence';
import replace from 'replace';
import webpack from 'webpack';
import get from 'lodash/object/get';
import defaults from 'lodash/object/defaults';
import {server} from 'electron-connect';
import {version} from './package.json';
/**
* Environments and constants.
*/
const DEBUG = !(process.argv.includes('--release') || process.argv.includes('release'));
const WATCH = process.argv.includes('--watch') || process.argv.includes('watch');
defaults(process.env, {
NODE_ENV: DEBUG ? 'development' : 'production',
ELECTRON: '0.35.1',
ARCHITECTURE: 'all',
});
switch (process.env.NODE_ENV) {
case 'production':
defaults(process.env, {ENDPOINT: 'https://myproduct.production'});
break;
default:
defaults(process.env, {ENDPOINT: 'http://myproduct.development'});
break;
}
util.log(chalk.green(`NODE_ENV: ${process.env.NODE_ENV}`));
util.log(chalk.green(`ENDPOINT: ${process.env.ENDPOINT}`));
util.log(chalk.green(`ELECTRON: v${process.env.ELECTRON}`));
let electron;
/**
* Helper functions.
*/
const copy = (source, destination) => new Promise((resolve, reject) => {
ncp(source, destination, err => err ? reject(err) : resolve());
});
const exec = command => new Promise((resolve, reject) => {
cp.exec(command, (err, stdout, stderr) => err ? reject(err) : resolve({stdout, stderr}));
});
const watch = pattern => new Promise((resolve, reject) => {
gaze(pattern, (err, watcher) => err ? reject(err) : resolve(watcher));
});
const packaging = opts => new Promise((resolve, reject) => {
packager(opts, (err, appPath) => err ? reject(err) : resolve(appPath));
});
/**
* Packages the project from source files into an application.
*/
gulp.task('release', async () => {
await del(['release/*', '!release/*.zip'], {dot: false});
await new Promise(resolve => run('build', resolve));
const appPaths = await packaging({
dir: 'build',
name: 'My Product',
arch: 'x64',
platform: process.env.ARCHITECTURE,
version: process.env.ELECTRON,
'app-bundle-id': 'production.myproduct',
'app-version': version,
asar: true,
prune: true,
overwrite: true,
icon: './src/resource/icon',
out: './release',
cache: './tmp/cache',
});
if (os.platform() === 'darwin') {
for (const index in appPaths) if (appPaths.hasOwnProperty(index)) {
const origin = appPaths[index];
const target = `${origin}-v${version}.zip`;
process.stdout.write(`Archiving app for platform ${origin.replace(/^.+-(.+?)-([^-]+?)$/, '$1 $2')}`);
const start = Date.now();
await exec(`ditto -ck --rsrc --sequesterRsrc "${origin}" "${target}"`);
const osize = (await exec(`du -sh "${origin}" | cut -f1`)).stdout;
const tsize = (await exec(`du -sh "${target}" | cut -f1`)).stdout;
process.stdout.write(` ${osize.trim()} -> ${tsize.trim()} (${Date.now() - start}ms)\n`);
}
} else {
util.log('Archiver only works in osx.');
}
});
/**
* Compiles the project from source files into a distributable format and copies it to the output (build) folder.
*/
gulp.task('build', async () => {
await new Promise(resolve => run('clean', 'copy', 'bundle', resolve));
});
/**
* Cleans up the output (build) directory.
*/
gulp.task('clean', async () => {
await del(['build/*'], {dot: false});
});
/**
* Copies static files to the output (build) folder.
*/
gulp.task('copy', async () => {
await Promise.all([
copy('src/resource', 'build/resource'),
copy('src/core/index.html', 'build/index.html'),
copy('package.json', 'build/package.json'),
]);
replace({
regex: '"main".*',
replacement: '"main": "bundle.core.js",',
paths: ['build/package.json'],
recursive: false,
silent: true,
});
if (WATCH) {
const watcher = await watch('src/core/**/*.html');
watcher.on('changed', async file => {
util.log('[changed]', file);
await copy(file, `build/${path.basename(file)}`);
electron.reload();
});
}
});
/**
* Bundles JavaScript into one or more packages ready to be used in a browser.
*/
gulp.task('bundle', async () => {
const config = require('./webpack.config.babel');
await new Promise((resolve, reject) => {
let count = 0;
const bundler = webpack(config);
const bundle = (error, stats) => {
if (error) {
reject(new util.PluginError('bundle', error.message));
} else {
util.log(stats.toString(config[0].stats));
if (++count === (WATCH ? config.length : 1)) {
if (WATCH) {
electron = server.create({path: 'build', electron: require('electron-prebuilt')});
electron.start();
}
resolve();
} else if (WATCH && count > config.length) {
const info = stats.toJson(config[0].stats);
if (/\.core\.js$/.test(get(info, 'assetsByChunkName.main'))) {
electron.restart();
} else {
electron.reload();
}
}
}
};
if (WATCH) {
bundler.watch(200, bundle);
} else {
bundler.run(bundle);
}
});
});
{
"name": "electron",
"version": "1.0.0",
"private": true,
"description": "Desktop application for My Product",
"main": "src/core/index.js",
"engines": {
"node": ">=4.2 <5.0"
},
"scripts": {
"test": "eslint . && exit 0",
"build": "gulp build",
"start": "gulp build --watch",
"release": "gulp release"
},
"dependencies": {},
"devDependencies": {
"babel": "^5.8.34",
"babel-eslint": "^4.1.6",
"babel-loader": "^5.4.0",
"chalk": "^1.1.1",
"css-loader": "^0.23.0",
"del": "^2.1.0",
"electron-connect": "^0.3.3",
"electron-packager": "^5.1.1",
"electron-prebuilt": "^0.35.1",
"eslint": "^1.10.1",
"eslint-config-airbnb": "^1.0.2",
"eslint-plugin-react": "^3.10.0",
"file-loader": "^0.8.5",
"gaze": "^0.5.2",
"gulp": "^3.9.0",
"gulp-electron": "0.0.9",
"gulp-util": "^3.0.7",
"json-loader": "^0.5.4",
"lodash": "^3.10.1",
"ncp": "^2.0.0",
"replace": "^0.3.0",
"run-sequence": "^1.1.5",
"style-loader": "^0.13.0",
"stylus-loader": "^1.4.2",
"url-loader": "^0.5.7",
"webpack": "^1.12.9"
}
}
import util from 'gulp-util';
import chalk from 'chalk';
import merge from 'lodash/object/merge';
import webpack from 'webpack';
const DEBUG = !(process.argv.includes('--release') || process.argv.includes('release')) || process.env.NODE_ENV !== 'production';
const VERBOSE = process.argv.includes('--verbose') || process.argv.includes('verbose');
util.log(chalk.green(`DEBUG: ${DEBUG ? 'on' : 'off'}`));
util.log(chalk.green(`VERBOSE: ${VERBOSE ? 'on' : 'off'}`));
const config = {
output: {
path: './build',
libraryTarget: 'commonjs2',
},
cache: DEBUG,
debug: DEBUG,
devtool: DEBUG ? 'cheap-module-eval-source-map' : false,
stats: {
colors: true,
reasons: DEBUG,
hash: VERBOSE,
version: VERBOSE,
timings: true,
warnings: VERBOSE,
chunks: VERBOSE,
chunkModules: VERBOSE,
cached: VERBOSE,
cachedAssets: VERBOSE,
},
target: 'node',
node: {
__dirname: false,
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.ExternalsPlugin('commonjs', ['electron', 'screen', 'remote']),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'process.env.ENDPOINT': JSON.stringify(process.env.ENDPOINT),
}),
...(DEBUG ? [] : [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin({compress: {warnings: VERBOSE}}),
new webpack.optimize.AggressiveMergingPlugin(),
]),
],
resolve: {
extensions: ['', '.js', '.jsx'],
},
module: {
loaders: [
{test: /\.jsx?$/, exclude: /node_modules/, loaders: ['babel']},
{test: /\.json$/, loaders: ['json']},
{test: /\.styl$/, loaders: ['style', 'css', 'stylus']},
{test: /\.png$/, loaders: ['url']},
],
},
};
const scriptConfig = merge({}, config, {
entry: './src/script/index.js',
output: {
filename: 'bundle.script.js',
},
});
const coreConfig = merge({}, config, {
entry: './src/core/index.js',
output: {
filename: 'bundle.core.js',
},
});
export default [scriptConfig, coreConfig];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment