diff --git a/.eslintrc.js b/.eslintrc.js index 311a9b6..0235b85 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,25 +1,26 @@ module.exports = { - "extends": "standard", - "env": { - "browser": true, - "mocha": true, - "node": true - }, - "rules": { - "react/jsx-uses-react": 2, - "react/jsx-uses-vars": 2, - "react/react-in-jsx-scope": 2, - "react/sort-comp": 0, - "react/no-multi-comp": 0, - "comma-dangle": 0, - "id-length": 0, - "new-cap": 0, - "eol-last": 0, - "jsx-quotes": 0, - "consistent-return": 0 - }, - "plugins": [ - "standard", - "react" - ] + // "parser": "babel-eslint", + "extends": "standard", + "env": { + "browser": true, + "mocha": true, + "node": true + }, + "rules": { + "react/jsx-uses-react": 2, + "react/jsx-uses-vars": 2, + "react/react-in-jsx-scope": 2, + "react/sort-comp": 0, + "react/no-multi-comp": 0, + "comma-dangle": 0, + "id-length": 0, + "new-cap": 0, + "eol-last": 0, + "jsx-quotes": 0, + "consistent-return": 0 + }, + "plugins": [ + "standard", + "react" + ] } diff --git a/.gitignore b/.gitignore index f991d21..1c7c8d8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,33 @@ -.DS_Store +# 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 + +# 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 -!/app/node_modules -npm-debug.log -*.test + +# OSX +.DS_Store + +# App packaged dist +release +main.js +main.js.map diff --git a/icons/logo.icns b/icons/logo.icns new file mode 100644 index 0000000..20063f0 Binary files /dev/null and b/icons/logo.icns differ diff --git a/icons/logo.ico b/icons/logo.ico new file mode 100644 index 0000000..9dac412 Binary files /dev/null and b/icons/logo.ico differ diff --git a/icons/logo.png b/icons/logo.png new file mode 100644 index 0000000..a974159 Binary files /dev/null and b/icons/logo.png differ diff --git a/main.dev.js b/main.dev.js new file mode 100644 index 0000000..0290aa7 --- /dev/null +++ b/main.dev.js @@ -0,0 +1,39 @@ +'use strict' + +import { app, BrowserWindow } from 'electron' + +let mainWindow = null + +app.on('window-all-closed', () => { + app.quit() +}) + +let winProps = { + width: 1000, + height: 800 +} + +if (process.env.NODE_ENV !== 'development') { + winProps = { + width: 800, + height: 350, + frame: true, + resizeable: false + } +} + +app.on('ready', () => { + mainWindow = new BrowserWindow(winProps) + + // mainWindow.loadURL('http://douban.fm') + + mainWindow.loadURL(`file://${__dirname}/index.html`) + + // if (process.env.NODE_ENV === 'development') { + mainWindow.webContents.openDevTools() + // } + + mainWindow.on('closed', () => { + mainWindow = null + }) +}) diff --git a/main.js b/main.js index d58dd5d..678f08b 100644 --- a/main.js +++ b/main.js @@ -1,42 +1,2 @@ -'use strict' - -import electron from 'electron' - -const app = electron.app -const BrowserWindow = electron.BrowserWindow - -let mainWindow = null - -app.on('window-all-closed', () => { - app.quit() -}) - -let winProps = { - width: 1000, - height: 800 -} - -if (process.env.NODE_ENV !== 'development') { - winProps = { - width: 800, - height: 350, - frame: true, - resizeable: false - } -} - -app.on('ready', () => { - mainWindow = new BrowserWindow(winProps) - - // mainWindow.loadURL('http://douban.fm') - - mainWindow.loadURL(`file://${__dirname}/index.html`) - - if (process.env.NODE_ENV === 'development') { - mainWindow.webContents.openDevTools() - } - - mainWindow.on('closed', () => { - mainWindow = null - }) -}) +!function(e){function n(t){if(o[t])return o[t].exports;var r=o[t]={exports:{},id:t,loaded:!1};return e[t].call(r.exports,r,r.exports,n),r.loaded=!0,r.exports}var o={};return n.m=e,n.c=o,n.p="",n(0)}([function(e,n,o){"use strict";var t=o(1),r=null;t.app.on("window-all-closed",function(){t.app.quit()});var i={width:1e3,height:800};i={width:800,height:350,frame:!0,resizeable:!1},t.app.on("ready",function(){r=new t.BrowserWindow(i),r.loadURL("file://"+__dirname+"/index.html"),r.webContents.openDevTools(),r.on("closed",function(){r=null})})},function(e,n){e.exports=require("electron")}]); +//# sourceMappingURL=main.js.map \ No newline at end of file diff --git a/package.js b/package.js new file mode 100644 index 0000000..bc60a43 --- /dev/null +++ b/package.js @@ -0,0 +1,134 @@ +'use strict' + +import os from 'os' +import webpack from 'webpack' +import packager from 'electron-packager' +import del from 'del' +import { exec } from 'child_process' +import parseArgs from 'minimist' + +import electronCfg from './webpack.config.electron' +import proCfg from './webpack.config.pro' +import pkg from './package' + +const argv = parseArgs(process.argv.slice(2)) + +// const deps = Object.keys(pkg.dependencies) +// const devDeps = Object.keys(pkg.devDependencies) + +const appName = argv.name || argv.n || pkg.productName +const shouldUseAsar = argv.asar || argv.a || false +const shouldBuildAll = argv.all || false + +const DEFAULT_OPTS = { + dir: './', + name: appName, + asar: shouldUseAsar, + ignore: [ + '/test($|/)', + '/tools($|/)', + '/release($|/)', + '/main.dev.js', + 'webpack.config.*', + 'screen.png', + '/node_modules/', + '/app/' + ] + // .concat(devDeps.map((name) => `/node_modules/${name}($|/)`)) + // .concat( + // deps.filter((name) => !electronCfg.externals.includes(name)) + // .map((name) => `/node_modules/${name}($|/)`) + // ) +} + +const icon = argv.icon || argv.i || 'icons/logo' + +if (icon) { + DEFAULT_OPTS.icon = icon +} + +const version = argv.version || argv.v + +if (version) { + DEFAULT_OPTS.version = version + startPack() +} else { + // use the same version as the currently-installed electron-prebuilt + exec('npm list electron-prebuilt --dev', (err, stdout) => { + if (err) { + DEFAULT_OPTS.version = '0.37.6' + } else { + DEFAULT_OPTS.version = stdout.split('electron-prebuilt@')[1].replace(/\s/g, '') + } + startPack() + }) +} + +function build (cfg) { + return new Promise((resolve, reject) => { + webpack(cfg, (err, stats) => { + if (err) return reject(err) + resolve(stats) + }) + }) +} + +function startPack () { + console.log('start pack...') + build(electronCfg) + .then(() => build(proCfg)) + .then(() => del('release/**', { force: true })) + .then((paths) => { + if (shouldBuildAll) { + // build for all platforms + const archs = ['ia32', 'x64'] + const platforms = ['linux', 'win32', 'darwin'] + + platforms.forEach((plat) => { + archs.forEach((arch) => { + pack(plat, arch, log(plat, arch)) + }) + }) + } else { + // build for current platform only + pack(os.platform(), os.arch(), log(os.platform(), os.arch())) + } + }) + .catch((err) => { + console.error(err) + }) +} + +function pack (plat, arch, cb) { + // there is no darwin ia32 electron + if (plat === 'darwin' && arch === 'ia32') return + + const iconObj = { + icon: DEFAULT_OPTS.icon + (() => { + let extension = '.png' + if (plat === 'darwin') { + extension = '.icns' + } else if (plat === 'win32') { + extension = '.ico' + } + return extension + })() + } + + const opts = Object.assign({}, DEFAULT_OPTS, iconObj, { + platform: plat, + arch, + prune: true, + 'app-version': pkg.version || DEFAULT_OPTS.version, + out: `release/${plat}-${arch}` + }) + + packager(opts, cb) +} + +function log (plat, arch) { + return (err, filepath) => { + if (err) return console.error(err) + console.log(`${plat}-${arch} finished!`) + } +} diff --git a/package.json b/package.json index f172866..52adfe8 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,16 @@ { "name": "douban.fm", + "productName": "doubanFM", "version": "1.0.0", "description": "豆瓣fm的桌面版", "main": "main.js", "scripts": { "lint": "eslint app test *.js", "server-hot": "node -r babel-register dev-server.js", - "start-hot": "NODE_ENV=development electron -r babel-register ./", - "build-renderer": "NODE_ENV=production node -r babel-register ./node_modules/.bin/webpack --config webpack.config.pro.js --progress --profile --colors", - "start": "NODE_ENV=production electron -r babel-register ./", + "start-hot": "cross-env NODE_ENV=development electron -r babel-register ./main.dev", + "build-renderer": "cross-env NODE_ENV=production node -r babel-register ./node_modules/.bin/webpack --config webpack.config.pro.js --progress --profile --colors", + "start": "cross-env NODE_ENV=production electron -r babel-register ./main.dev", + "package": "cross-env NODE_ENV=production node -r babel-register package.js", "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { @@ -27,12 +29,15 @@ "devDependencies": { "babel": "^6.5.2", "babel-core": "^6.7.2", + "babel-eslint": "^6.0.3", "babel-loader": "^6.2.4", + "babel-polyfill": "^6.7.4", "babel-preset-es2015": "^6.5.0", "babel-preset-react": "^6.5.0", "babel-preset-stage-0": "^6.5.0", "babel-register": "^6.7.2", "css-loader": "^0.23.1", + "del": "^2.2.0", "electron-builder": "^2.8.3", "electron-packager": "^5.2.1", "electron-prebuilt": "^0.37.2", @@ -44,8 +49,8 @@ "express": "^4.13.4", "extract-text-webpack-plugin": "^1.0.1", "gulp": "^3.9.1", - "html-webpack-plugin": "^2.15.0", "json-loader": "^0.5.4", + "minimist": "^1.2.0", "node-sass": "^3.5.3", "react-hot-loader": "^1.3.0", "sass-loader": "^3.2.0", diff --git a/webpack.config.electron.js b/webpack.config.electron.js new file mode 100644 index 0000000..3b1d389 --- /dev/null +++ b/webpack.config.electron.js @@ -0,0 +1,55 @@ +// translate main.js + +import webpack from 'webpack' +import baseConfig from './webpack.config.base' + +export default { + ...baseConfig, + + devtool: 'source-map', + + entry: './main.dev', + + output: { + path: __dirname, + filename: './main.js' + }, + + module: { + loaders: [ + ...baseConfig.module.loaders, + { + test: /\.js$/, + exclude: /node_modules/, + loaders: ['babel'] + } + ] + }, + + plugins: [ + new webpack.optimize.UglifyJsPlugin({ + compressor: { + warnings: false + } + }), + // new webpack.BannerPlugin( + // 'require("source-map-support").install();', + // { raw: true, entryOnly: false } + // ), + new webpack.DefinePlugin({ + 'process.env': { + NODE_ENV: JSON.stringify('production') + } + }) + ], + + node: { + __dirname: false, + __filename: false + }, + + // externals: [ + // ...baseConfig.externals, + // 'source-map-support' + // ] +}