diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..b0b9a96
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,3 @@
+{
+ "stage": 0
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3c252c7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,33 @@
+# Logs
+logs
+*.log
+
+# Runtime data
+pids
+*.pid
+*.seed
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (http://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directory
+# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
+node_modules
+
+# OSX
+.DS_Store
+
+# App packaged
+release
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..0e10cbc
--- /dev/null
+++ b/README.md
@@ -0,0 +1,6 @@
+GraphiQL.app
+------------
+
+A light, Electron-based wrapper around GraphiQL.
+
+This is a WIP, and was made in about an hour. It will get better over time.
diff --git a/app/app.css b/app/app.css
new file mode 100644
index 0000000..98030da
--- /dev/null
+++ b/app/app.css
@@ -0,0 +1,57 @@
+.clearfix:after {
+ visibility: hidden;
+ display: block;
+ font-size: 0;
+ content: " ";
+ clear: both;
+ height: 0;
+ }
+.clearfix { display: inline-block; }
+/* start commented backslash hack \*/
+* html .clearfix { height: 1%; }
+.clearfix { display: block; }
+/* close commented backslash hack */
+
+body {
+ font-family: helvetica, arial, sans-serif;
+}
+
+#react-root {
+ width: 100%;
+ height: 100%;
+}
+
+.ReactModal__Overlay {
+ z-index: 10000000;
+}
+
+.wrapper {
+ width: 100%;
+ height: 100%;
+}
+
+.config-form {
+ padding: 20px;
+}
+
+.field {
+ display: flex;
+ height: 40px;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ float: left;
+ margin-right: 30px;
+}
+
+.field label {
+ margin-right: 20px;
+ line-height: 35px;
+}
+
+.field input, .field select {
+ height: 25px;
+ padding: 5px;
+ font-weight: bold;
+ font-size: 20px;
+}
diff --git a/app/app.html b/app/app.html
new file mode 100755
index 0000000..498e26e
--- /dev/null
+++ b/app/app.html
@@ -0,0 +1,13 @@
+
+
+
+
+ GraphiQL
+
+
+
+
+
+
+
+
diff --git a/app/app.icns b/app/app.icns
new file mode 100755
index 0000000..5ef78ea
Binary files /dev/null and b/app/app.icns differ
diff --git a/app/components/App.js b/app/components/App.js
new file mode 100644
index 0000000..0fda2f3
--- /dev/null
+++ b/app/components/App.js
@@ -0,0 +1,104 @@
+import _ from 'lodash';
+import React from 'react';
+import fetch from 'isomorphic-fetch';
+import GraphiQL from 'graphiql/dist/index';
+import Modal from 'react-modal/lib/index';
+
+Modal.setAppElement(document.getElementById('react-root'));
+Modal.injectCSS();
+
+import HTTPHeaderEditor from './HTTPHeaderEditor';
+
+
+export default class App extends React.Component {
+ constructor() {
+ super();
+
+ const storage = window.localStorage;
+
+ this.state = {
+ headers: JSON.parse(storage.getItem('graphiqlHeaders') || '{}'),
+ endpoint: storage.getItem('graphiqlEndpoint') || 'http://localhost:9000/data',
+ method: storage.getItem('graphiqlMethod') || 'post',
+ headerEditOpen: false
+ }
+ }
+
+ updateLocalStorage() {
+ window.localStorage.setItem('graphiqlHeaders', JSON.stringify(this.state.headers));
+ window.localStorage.setItem('graphiqlEndpoint', this.state.endpoint);
+ window.localStorage.setItem('graphiqlMethod', this.state.method);
+ }
+
+ graphQLFetcher = (graphQLParams) => {
+ const defaultHeaders = {
+ 'Content-Type': 'application/json'
+ };
+
+ return fetch(this.state.endpoint, {
+ method: this.state.method,
+ headers: Object.assign({}, defaultHeaders, this.state.headers),
+ body: JSON.stringify(graphQLParams)
+ }).then(response => response.json());
+ }
+
+ handleChange(field, e) {
+ this.setState({
+ [field]: e.target.value
+ }, () => {
+ this.updateLocalStorage();
+ });
+ }
+
+ openHeaderEdit = () => {
+ this.setState({
+ headerEditOpen: true
+ });
+ }
+
+ closeModal = () => {
+ this.setState({
+ headerEditOpen: false
+ });
+ }
+
+ getHeadersFromModal = (headers) => {
+ this.setState({
+ headers: headers
+ }, () => {
+ this.updateLocalStorage();
+ });
+ }
+
+ render() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ({ key, value }))}
+ onCreateHeaders={this.getHeadersFromModal}
+ closeModal={this.closeModal} />
+
+
+ );
+ }
+}
diff --git a/app/components/HTTPHeaderEditor.js b/app/components/HTTPHeaderEditor.js
new file mode 100644
index 0000000..2049917
--- /dev/null
+++ b/app/components/HTTPHeaderEditor.js
@@ -0,0 +1,117 @@
+import _ from 'lodash';
+import React from 'react';
+// import Radium from 'radium';
+
+export default class HTTPHeaderEditor extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ headers: props.headers || [],
+ addingHeader: false
+ };
+ }
+
+ sendHeaderListUpdate() {
+ if (this.props.onCreateHeaders) {
+ this.props.onCreateHeaders(
+ _.zipObject(_.map(this.state.headers, (val) => [val.key, val.value]))
+ );
+ }
+ }
+
+ addHeader = () => {
+ this.setState({
+ addingHeader: true
+ });
+ }
+
+ completeAdd = () => {
+ this.setState({
+ headers: [
+ ...this.state.headers,
+ {
+ key: React.findDOMNode(this.newKeyInput).value,
+ value: React.findDOMNode(this.newValInput).value
+ }
+ ]
+ }, () => {
+ this.setState({
+ addingHeader: false
+ });
+ this.sendHeaderListUpdate();
+ });
+ }
+
+ cancelAdd = () => {
+ this.setState({
+ addingHeader: false
+ });
+ }
+
+ removeRow = (i, event) => {
+ const newHeaders = [...this.state.headers];
+ newHeaders.splice(i, 1);
+ this.setState({
+ headers: newHeaders
+ }, () => {
+ this.sendHeaderListUpdate();
+ });
+ }
+
+ render() {
+ let addHeader = null;
+
+ if (this.state.addingHeader) {
+ addHeader = (
+
+ {
+ this.newKeyInput = c;
+ }} type="text" placeholder="Header Key" /> |
+ {
+ this.newValInput = c;
+ }} type="text" placeholder="Header Value" /> |
+
+
+
+ |
+
+ )
+ }
+
+ return (
+
+
Edit HTTP Headers
+
+
+ Add Header
+
+
+ Key |
+ Value |
+ |
+
+
+ {this.state.headers.map((header, i) => (
+
+ {header.key} |
+ {header.value.length > 40 ? header.value.substr(0, 40) + '...' : header.value} |
+
+
+ |
+
+ ))}
+ {addHeader}
+
+
+
+
+ );
+ }
+}
+
+const styles = {
+ table: {
+ marginTop: 10,
+ width: '100%'
+ }
+}
diff --git a/app/hot-dev-app.html b/app/hot-dev-app.html
new file mode 100755
index 0000000..5cb81ea
--- /dev/null
+++ b/app/hot-dev-app.html
@@ -0,0 +1,12 @@
+
+
+
+
+ GraphiQL
+
+
+
+
+
+
+
diff --git a/app/mainApp.jsx b/app/mainApp.jsx
new file mode 100644
index 0000000..34cf2e3
--- /dev/null
+++ b/app/mainApp.jsx
@@ -0,0 +1,8 @@
+import './app.css';
+import 'graphiql/graphiql.css';
+
+import React from 'react';
+
+import App from './components/App';
+
+React.render(, document.getElementById('react-root'))
diff --git a/dist/.gitignore b/dist/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/dist/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/main.js b/main.js
new file mode 100644
index 0000000..ba447eb
--- /dev/null
+++ b/main.js
@@ -0,0 +1,223 @@
+var app = require('app');
+var BrowserWindow = require('browser-window');
+var Menu = require('menu');
+var menu, template;
+
+if (process.env.NODE_ENV !== 'production') {
+ require('electron-debug')();
+}
+require('crash-reporter').start();
+
+var mainWindow = null;
+
+app.on('window-all-closed', function() {
+ if (process.platform !== 'darwin') app.quit();
+});
+
+
+app.on('ready', function() {
+
+ mainWindow = new BrowserWindow({ width: 1024, height: 728 });
+
+ if (process.env.HOT) {
+ mainWindow.loadUrl('file://' + __dirname + '/app/hot-dev-app.html');
+ } else {
+ mainWindow.loadUrl('file://' + __dirname + '/app/app.html');
+ }
+
+ mainWindow.on('closed', function() {
+ mainWindow = null;
+ });
+
+ if (process.env.NODE_ENV === 'development') {
+ mainWindow.openDevTools();
+ }
+
+ if (process.platform === 'darwin') {
+ template = [{
+ label: 'GraphiQL',
+ submenu: [{
+ label: 'About GraphiQL',
+ selector: 'orderFrontStandardAboutPanel:'
+ }, {
+ type: 'separator'
+ }, {
+ label: 'Services',
+ submenu: []
+ }, {
+ type: 'separator'
+ }, {
+ label: 'Hide GraphiQL',
+ accelerator: 'Command+H',
+ selector: 'hide:'
+ }, {
+ label: 'Hide Others',
+ accelerator: 'Command+Shift+H',
+ selector: 'hideOtherApplications:'
+ }, {
+ label: 'Show All',
+ selector: 'unhideAllApplications:'
+ }, {
+ type: 'separator'
+ }, {
+ label: 'Quit',
+ accelerator: 'Command+Q',
+ click: function() {
+ app.quit();
+ }
+ }]
+ }, {
+ label: 'Edit',
+ submenu: [{
+ label: 'Undo',
+ accelerator: 'Command+Z',
+ selector: 'undo:'
+ }, {
+ label: 'Redo',
+ accelerator: 'Shift+Command+Z',
+ selector: 'redo:'
+ }, {
+ type: 'separator'
+ }, {
+ label: 'Cut',
+ accelerator: 'Command+X',
+ selector: 'cut:'
+ }, {
+ label: 'Copy',
+ accelerator: 'Command+C',
+ selector: 'copy:'
+ }, {
+ label: 'Paste',
+ accelerator: 'Command+V',
+ selector: 'paste:'
+ }, {
+ label: 'Select All',
+ accelerator: 'Command+A',
+ selector: 'selectAll:'
+ }]
+ }, {
+ label: 'View',
+ submenu: [{
+ label: 'Reload',
+ accelerator: 'Command+R',
+ click: function() {
+ mainWindow.restart();
+ }
+ }, {
+ label: 'Toggle Full Screen',
+ accelerator: 'Ctrl+Command+F',
+ click: function() {
+ mainWindow.setFullScreen(!mainWindow.isFullScreen());
+ }
+ }, {
+ label: 'Toggle Developer Tools',
+ accelerator: 'Alt+Command+I',
+ click: function() {
+ mainWindow.toggleDevTools();
+ }
+ }]
+ }, {
+ label: 'Window',
+ submenu: [{
+ label: 'Minimize',
+ accelerator: 'Command+M',
+ selector: 'performMiniaturize:'
+ }, {
+ label: 'Close',
+ accelerator: 'Command+W',
+ selector: 'performClose:'
+ }, {
+ type: 'separator'
+ }, {
+ label: 'Bring All to Front',
+ selector: 'arrangeInFront:'
+ }]
+ }, {
+ label: 'Help',
+ submenu: [{
+ label: 'Learn More',
+ click: function() {
+ require('shell').openExternal('http://electron.atom.io');
+ }
+ }, {
+ label: 'Documentation',
+ click: function() {
+ require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme');
+ }
+ }, {
+ label: 'Community Discussions',
+ click: function() {
+ require('shell').openExternal('https://discuss.atom.io/c/electron');
+ }
+ }, {
+ label: 'Search Issues',
+ click: function() {
+ require('shell').openExternal('https://github.com/atom/electron/issues');
+ }
+ }]
+ }];
+
+ menu = Menu.buildFromTemplate(template);
+ Menu.setApplicationMenu(menu);
+ } else {
+ template = [{
+ label: '&File',
+ submenu: [{
+ label: '&Open',
+ accelerator: 'Ctrl+O'
+ }, {
+ label: '&Close',
+ accelerator: 'Ctrl+W',
+ click: function() {
+ mainWindow.close();
+ }
+ }]
+ }, {
+ label: '&View',
+ submenu: [{
+ label: '&Reload',
+ accelerator: 'Ctrl+R',
+ click: function() {
+ mainWindow.restart();
+ }
+ }, {
+ label: 'Toggle &Full Screen',
+ accelerator: 'F11',
+ click: function() {
+ mainWindow.setFullScreen(!mainWindow.isFullScreen());
+ }
+ }, {
+ label: 'Toggle &Developer Tools',
+ accelerator: 'Alt+Ctrl+I',
+ click: function() {
+ mainWindow.toggleDevTools();
+ }
+ }]
+ }, {
+ label: 'Help',
+ submenu: [{
+ label: 'Learn More',
+ click: function() {
+ require('shell').openExternal('http://electron.atom.io');
+ }
+ }, {
+ label: 'Documentation',
+ click: function() {
+ require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme');
+ }
+ }, {
+ label: 'Community Discussions',
+ click: function() {
+ require('shell').openExternal('https://discuss.atom.io/c/electron');
+ }
+ }, {
+ label: 'Search Issues',
+ click: function() {
+ require('shell').openExternal('https://github.com/atom/electron/issues');
+ }
+ }]
+ }];
+ menu = Menu.buildFromTemplate(template);
+ mainWindow.setMenu(menu);
+ }
+});
diff --git a/package.js b/package.js
new file mode 100644
index 0000000..881104d
--- /dev/null
+++ b/package.js
@@ -0,0 +1,94 @@
+var os = require('os')
+var webpack = require('webpack')
+var cfg = require('./webpack/webpack.config.production.js')
+var packager = require('electron-packager')
+var assign = require('object-assign')
+var del = require('del')
+var latest = require('github-latest-release')
+var argv = require('minimist')(process.argv.slice(2))
+var devDeps = Object.keys(require('./package.json').devDependencies)
+
+
+var appName = argv.name || argv.n || 'ElectronReact'
+var shouldUseAsar = argv.asar || argv.a || false
+var shouldBuildAll = argv.all || false
+
+
+var DEFAULT_OPTS = {
+ dir: './',
+ name: appName,
+ asar: shouldUseAsar,
+ ignore: [
+ '/test($|/)',
+ '/tools($|/)',
+ '/release($|/)'
+ ].concat(devDeps.map(function(name) { return '/node_modules/' + name + '($|/)' }))
+}
+
+var icon = argv.icon || argv.i || 'app/app.icns'
+
+if (icon) {
+ DEFAULT_OPTS.icon = icon
+}
+
+var version = argv.version || argv.v
+
+if (version) {
+ DEFAULT_OPTS.version = version
+ startPack()
+} else {
+ latest('atom', 'electron', function(err, res) {
+ if (err) {
+ DEFAULT_OPTS.version = '0.28.3'
+ } else {
+ DEFAULT_OPTS.version = res.name.split('v')[1]
+ }
+ startPack()
+ })
+}
+
+
+function startPack() {
+ console.log('start pack...')
+ webpack(cfg, function(err, stats) {
+ if (err) return console.error(err)
+ del('release', function(err, paths) {
+ if (err) return console.error(err)
+ if (shouldBuildAll) {
+ // build for all platforms
+ var archs = ['ia32', 'x64']
+ var platforms = ['linux', 'win32', 'darwin']
+
+ platforms.forEach(function (plat) {
+ archs.forEach(function (arch) {
+ pack(plat, arch, log(plat, arch))
+ })
+ })
+ } else {
+ // build for current platform only
+ pack(os.platform(), os.arch(), log(os.platform(), os.arch()))
+ }
+ })
+ })
+}
+
+function pack(plat, arch, cb) {
+ // there is no darwin ia32 electron
+ if (plat === 'darwin' && arch === 'ia32') return
+
+ var opts = assign({}, DEFAULT_OPTS, {
+ platform: plat,
+ arch: arch,
+ out: 'release/' + plat + '-' + arch
+ })
+
+ packager(opts, cb)
+}
+
+
+function log(plat, arch) {
+ return function(err, filepath) {
+ if (err) return console.error(err)
+ console.log(plat + '-' + arch + ' finished!')
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..9bde0d9
--- /dev/null
+++ b/package.json
@@ -0,0 +1,57 @@
+{
+ "name": "graphiql-app",
+ "version": "0.1.0",
+ "description": "A light, Electron-based wrapper around GraphiQL. WIP",
+ "main": "main.js",
+ "scripts": {
+ "dev-server": "webpack-dev-server --config webpack/webpack-dev-server.config.js --progress --colors --port 2992 --inline",
+ "hot-dev-server": "webpack-dev-server --config webpack/webpack-hot-dev-server.config.js --hot --progress --colors --port 2992 --inline",
+ "build": "webpack --config webpack/webpack.config.production.js --progress --profile --colors",
+ "start": "electron .",
+ "start-dev": "NODE_ENV=development electron .",
+ "start-hot": "HOT=1 NODE_ENV=development electron .",
+ "package": "node package.js --name=GraphiQL",
+ "package-all": "node package.js --name=GraphiQL --all"
+ },
+ "author": "Adam Miskiewicz (http://github.com/skevy)",
+ "license": "MIT",
+ "homepage": "https://github.com/skevy/graphiql-app",
+ "bugs": {
+ "url": "https://github.com/skevy/graphiql-app/issues"
+ },
+ "dependencies": {
+ "electron-debug": "^0.2.0",
+ "graphiql": "^0.1.0",
+ "graphql": "^0.4.2",
+ "isomorphic-fetch": "^2.1.1",
+ "lodash": "^3.10.1",
+ "object-assign": "^4.0.1",
+ "radium": "^0.13.8",
+ "react": "^0.13.3",
+ "react-modal": "^0.3.0"
+ },
+ "devDependencies": {
+ "asar": "^0.7.2",
+ "babel-core": "^5.8.22",
+ "babel-loader": "^5.3.2",
+ "babel-runtime": "^5.8.20",
+ "css-loader": "^0.16.0",
+ "del": "^1.2.1",
+ "electron-packager": "^5.0.2",
+ "electron-prebuilt": "^0.31.0",
+ "electron-rebuild": "^0.2.5",
+ "extract-text-webpack-plugin": "^0.8.2",
+ "file-loader": "^0.8.4",
+ "github-latest-release": "^0.1.1",
+ "html-loader": "^0.3.0",
+ "json-loader": "^0.5.2",
+ "minimist": "^1.2.0",
+ "raw-loader": "^0.5.1",
+ "react-hot-loader": "^1.2.9",
+ "stats-webpack-plugin": "^0.2.1",
+ "style-loader": "^0.12.3",
+ "url-loader": "^0.5.6",
+ "webpack": "^1.12.0",
+ "webpack-dev-server": "^1.10.1"
+ }
+}
diff --git a/webpack/loaders-by-extension.js b/webpack/loaders-by-extension.js
new file mode 100755
index 0000000..9b3ada8
--- /dev/null
+++ b/webpack/loaders-by-extension.js
@@ -0,0 +1,29 @@
+function extsToRegExp(exts) {
+ return new RegExp('\\.(' + exts.map(function(ext) {
+ return ext.replace(/\./g, '\\.')
+ }).join('|') + ')(\\?.*)?$')
+}
+
+module.exports = function loadersByExtension(obj) {
+ var loaders = []
+ Object.keys(obj).forEach(function(key) {
+ var exts = key.split('|')
+ var value = obj[key]
+ var entry = {
+ extensions: exts,
+ test: extsToRegExp(exts)
+ }
+
+ if (Array.isArray(value)) {
+ entry.loaders = value
+ } else if (typeof value === 'string') {
+ entry.loader = value
+ } else {
+ Object.keys(value).forEach(function(valueKey) {
+ entry[valueKey] = value[valueKey]
+ })
+ }
+ loaders.push(entry)
+ })
+ return loaders
+}
diff --git a/webpack/make-webpack-config.js b/webpack/make-webpack-config.js
new file mode 100755
index 0000000..ea9bee3
--- /dev/null
+++ b/webpack/make-webpack-config.js
@@ -0,0 +1,186 @@
+var webpack = require('webpack')
+var path = require('path')
+var fs = require('fs')
+var ExtractTextPlugin = require('extract-text-webpack-plugin')
+var StatsPlugin = require('stats-webpack-plugin')
+var loadersByExtension = require('./loaders-by-extension')
+
+var projectRoot = path.join(__dirname, '..')
+var appRoot = path.join(projectRoot, 'app')
+
+module.exports = function(opts) {
+
+ var entry = {
+ main: opts.prerender ? path.join(appRoot, 'mainApp') : path.join(appRoot, 'mainApp')
+ }
+
+
+ var loaders = {
+ 'jsx': opts.hotComponents ?
+ [ 'react-hot-loader', 'babel-loader?optional=runtime' ] : 'babel-loader?optional=runtime',
+ 'js': {
+ loader: 'babel-loader?optional=runtime',
+ include: appRoot
+ },
+ 'json': 'json-loader',
+ 'txt': 'raw-loader',
+ 'png|jpg|jpeg|gif|svg': 'url-loader?limit=10000',
+ 'woff|woff2': 'url-loader?limit=100000',
+ 'ttf|eot': 'file-loader',
+ 'wav|mp3': 'file-loader',
+ 'html': 'html-loader',
+ 'md|markdown': [ 'html-loader', 'markdown-loader' ]
+ }
+
+ var cssLoader = opts.minimize ? 'css-loader' : 'css-loader?localIdentName=[path][name]---[local]---[hash:base64:5]'
+
+ var stylesheetLoaders = {
+ 'css': cssLoader,
+ 'less': [ cssLoader, 'less-loader' ],
+ 'styl': [ cssLoader, 'stylus-loader' ],
+ 'scss|sass': [ cssLoader, 'sass-loader' ]
+ }
+
+ var additionalLoaders = [
+ // { test: /some-reg-exp$/, loader: 'any-loader' }
+ ]
+
+ var alias = {
+
+ }
+
+ var aliasLoader = {
+
+ }
+
+ var externals = [
+
+ ]
+
+ var modulesDirectories = [ 'node_modules' ]
+
+ var extensions = [ '', '.js', '.jsx', '.json', '.node' ]
+
+ var publicPath = opts.devServer
+ ? 'http://localhost:2992/dist/'
+ : '/dist/'
+
+
+ var output = {
+ path: projectRoot + '/dist/',
+ filename: 'bundle.js',
+ publicPath: publicPath,
+ contentBase: projectRoot + '/public/',
+ libraryTarget: 'commonjs2'
+ }
+
+ var excludeFromStats = [
+ /node_modules[\\\/]react(-router)?[\\\/]/
+ ]
+
+
+ var plugins = [
+ new webpack.PrefetchPlugin('react'),
+ new webpack.PrefetchPlugin('react/lib/ReactComponentBrowserEnvironment')
+ ]
+
+ if (opts.prerender) {
+ plugins.push(new StatsPlugin(path.join(projectRoot, 'dist', 'stats.prerender.json'), {
+ chunkModules: true,
+ exclude: excludeFromStats
+ }))
+ // aliasLoader['react-proxy$'] = 'react-proxy/unavailable'
+ // aliasLoader['react-proxy-loader$'] = 'react-proxy-loader/unavailable'
+ externals.push(
+ // /^react(\/.*)?$/
+ )
+ plugins.push(new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }))
+ } else {
+ plugins.push(new StatsPlugin(path.join(projectRoot, 'dist', 'stats.json'), {
+ chunkModules: true,
+ exclude: excludeFromStats
+ }));
+ }
+
+ if (opts.commonsChunk) {
+ plugins.push(new webpack.optimize.CommonsChunkPlugin('commons', 'commons.js' + (opts.longTermCaching && !opts.prerender ? '?[chunkhash]' : '')))
+ }
+
+ Object.keys(stylesheetLoaders).forEach(function(ext) {
+ var stylesheetLoader = stylesheetLoaders[ext]
+ if (Array.isArray(stylesheetLoader)) stylesheetLoader = stylesheetLoader.join('!')
+ if (opts.prerender) {
+ stylesheetLoaders[ext] = stylesheetLoader.replace(/^css-loader/, 'css-loader/locals')
+ } else if (opts.separateStylesheet) {
+ stylesheetLoaders[ext] = ExtractTextPlugin.extract('style-loader', stylesheetLoader)
+ } else {
+ stylesheetLoaders[ext] = 'style-loader!' + stylesheetLoader
+ }
+ })
+
+ if (opts.separateStylesheet && !opts.prerender) {
+ plugins.push(new ExtractTextPlugin('[name].css' + (opts.longTermCaching ? '?[contenthash]' : '')))
+ }
+
+ if (opts.minimize && !opts.prerender) {
+ plugins.push(
+ new webpack.optimize.UglifyJsPlugin({
+ compressor: {
+ warnings: false
+ }
+ }),
+ new webpack.optimize.DedupePlugin()
+ )
+ }
+
+ if (opts.minimize) {
+ plugins.push(
+ new webpack.DefinePlugin({
+ 'process.env': {
+ NODE_ENV: "'production'"
+ }
+ }),
+ new webpack.NoErrorsPlugin()
+ )
+ }
+
+ var nodeModules = fs.readdirSync('node_modules').filter(function(x) {
+ return x !== '.bin' && x !== 'react' && x !== 'react-router';
+ });
+
+ var electronModules = [
+ 'ipc',
+ 'remote',
+ 'web-frame',
+ 'clipboard',
+ 'crash-reporter',
+ 'native-image',
+ 'screen',
+ 'shell'
+ ];
+
+ return {
+ entry: entry,
+ output: output,
+ target: 'web',
+ externals: externals.concat(nodeModules).concat(electronModules),
+ module: {
+ loaders: [].concat(loadersByExtension(loaders)).concat(loadersByExtension(stylesheetLoaders)).concat(additionalLoaders)
+ },
+ devtool: opts.devtool,
+ debug: opts.debug,
+ resolve: {
+ root: appRoot,
+ modulesDirectories: modulesDirectories,
+ extensions: extensions,
+ alias: alias
+ },
+ plugins: plugins,
+ devServer: {
+ stats: {
+ cached: false,
+ exclude: excludeFromStats
+ }
+ }
+ }
+}
diff --git a/webpack/webpack-dev-server.config.js b/webpack/webpack-dev-server.config.js
new file mode 100755
index 0000000..1012534
--- /dev/null
+++ b/webpack/webpack-dev-server.config.js
@@ -0,0 +1,5 @@
+module.exports = require('./make-webpack-config')({
+ devServer: true,
+ devtool: 'eval',
+ debug: true
+})
diff --git a/webpack/webpack-hot-dev-server.config.js b/webpack/webpack-hot-dev-server.config.js
new file mode 100755
index 0000000..bd58db6
--- /dev/null
+++ b/webpack/webpack-hot-dev-server.config.js
@@ -0,0 +1,6 @@
+module.exports = require('./make-webpack-config')({
+ devServer: true,
+ hotComponents: true,
+ devtool: 'eval',
+ debug: true
+})
diff --git a/webpack/webpack.config.js b/webpack/webpack.config.js
new file mode 100755
index 0000000..73fa9e6
--- /dev/null
+++ b/webpack/webpack.config.js
@@ -0,0 +1,3 @@
+module.exports = require('./make-webpack-config')({})
+
+
diff --git a/webpack/webpack.config.production.js b/webpack/webpack.config.production.js
new file mode 100755
index 0000000..b826c27
--- /dev/null
+++ b/webpack/webpack.config.production.js
@@ -0,0 +1,7 @@
+module.exports = require('./make-webpack-config')({
+ // commonsChunk: true,
+ longTermCaching: true,
+ separateStylesheet: true,
+ minimize: true
+ // devtool: 'source-map'
+})