├── .babelrc ├── .build-config ├── build.js ├── dev-client.js ├── dev-runner.js ├── muti-page.config.js ├── webpack.main.config.js ├── webpack.renderer.config.js └── webpack.web.config.js ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .idea ├── Shorthands_PC.iml ├── inspectionProfiles │ └── Project_Default.xml ├── misc.xml ├── modules.xml ├── vcs.xml └── workspace.xml ├── .travis.yml ├── README.md ├── appveyor.yml ├── build └── icons │ ├── 256x256.png │ ├── icon.icns │ └── icon.ico ├── dist ├── electron │ ├── .gitkeep │ └── package.json └── web │ └── .gitkeep ├── package.json ├── src ├── index.ejs ├── main │ ├── index.dev.js │ ├── index.js │ └── newPage.js └── renderer │ └── page │ ├── main │ ├── App.vue │ ├── index.ejs │ ├── main.js │ ├── pages │ │ └── Main.vue │ └── router │ │ └── index.js │ └── newPage │ ├── App.vue │ ├── index.ejs │ ├── main.js │ ├── pages │ └── NewPage.vue │ └── router │ └── index.js └── static └── .gitkeep /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "comments": false, 3 | "env": { 4 | "main": { 5 | "presets": [ 6 | ["env", { 7 | "targets": { "node": 7 } 8 | }], 9 | "stage-0" 10 | ] 11 | }, 12 | "renderer": { 13 | "presets": [ 14 | ["env", { 15 | "modules": false 16 | }], 17 | "stage-0" 18 | ] 19 | }, 20 | "web": { 21 | "presets": [ 22 | ["env", { 23 | "modules": false 24 | }], 25 | "stage-0" 26 | ] 27 | } 28 | }, 29 | "plugins": ["transform-runtime"] 30 | } 31 | -------------------------------------------------------------------------------- /.build-config/build.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | process.env.NODE_ENV = 'production' 4 | 5 | const { say } = require('cfonts') 6 | const chalk = require('chalk') 7 | const del = require('del') 8 | const { spawn } = require('child_process') 9 | const webpack = require('webpack') 10 | const Multispinner = require('multispinner') 11 | 12 | console.log('node_env', process.env.NODE_ENV); 13 | 14 | const mainConfig = require('./webpack.main.config') 15 | const rendererConfig = require('./webpack.renderer.config') 16 | const webConfig = require('./webpack.web.config') 17 | 18 | const doneLog = chalk.bgGreen.white(' DONE ') + ' ' 19 | const errorLog = chalk.bgRed.white(' ERROR ') + ' ' 20 | const okayLog = chalk.bgBlue.white(' OKAY ') + ' ' 21 | const isCI = process.env.CI || false 22 | 23 | if (process.env.BUILD_TARGET === 'clean') clean() 24 | else if (process.env.BUILD_TARGET === 'web') web() 25 | else build() 26 | 27 | function clean () { 28 | del.sync(['build/*', '!build/icons', '!build/icons/icon.*']) 29 | console.log(`\n${doneLog}\n`) 30 | process.exit() 31 | } 32 | 33 | function build () { 34 | greeting() 35 | 36 | del.sync(['dist/electron/*', '!.gitkeep', '!dist/electron/package.json']) 37 | 38 | const tasks = ['main', 'renderer'] 39 | const m = new Multispinner(tasks, { 40 | preText: 'building', 41 | postText: 'process' 42 | }) 43 | 44 | let results = '' 45 | 46 | m.on('success', () => { 47 | process.stdout.write('\x1B[2J\x1B[0f') 48 | console.log(`\n\n${results}`) 49 | console.log(`${okayLog}take it away ${chalk.yellow('`electron-builder`')}\n`) 50 | process.exit() 51 | }) 52 | 53 | pack(mainConfig).then(result => { 54 | results += result + '\n\n' 55 | m.success('main') 56 | }).catch(err => { 57 | m.error('main') 58 | console.log(`\n ${errorLog}failed to build main process`) 59 | console.error(`\n${err}\n`) 60 | process.exit(1) 61 | }) 62 | 63 | pack(rendererConfig).then(result => { 64 | results += result + '\n\n' 65 | m.success('renderer') 66 | }).catch(err => { 67 | m.error('renderer') 68 | console.log(`\n ${errorLog}failed to build renderer process`) 69 | console.error(`\n${err}\n`) 70 | process.exit(1) 71 | }) 72 | } 73 | 74 | function pack (config) { 75 | return new Promise((resolve, reject) => { 76 | config.mode = 'production' 77 | webpack(config, (err, stats) => { 78 | if (err) reject(err.stack || err) 79 | else if (stats.hasErrors()) { 80 | let err = '' 81 | 82 | stats.toString({ 83 | chunks: false, 84 | colors: true 85 | }) 86 | .split(/\r?\n/) 87 | .forEach(line => { 88 | err += ` ${line}\n` 89 | }) 90 | 91 | reject(err) 92 | } else { 93 | resolve(stats.toString({ 94 | chunks: false, 95 | colors: true 96 | })) 97 | } 98 | }) 99 | }) 100 | } 101 | 102 | function web () { 103 | del.sync(['dist/web/*', '!.gitkeep']) 104 | webConfig.mode = 'production' 105 | webpack(webConfig, (err, stats) => { 106 | if (err || stats.hasErrors()) console.log(err) 107 | 108 | console.log(stats.toString({ 109 | chunks: false, 110 | colors: true 111 | })) 112 | 113 | process.exit() 114 | }) 115 | } 116 | 117 | function greeting () { 118 | const cols = process.stdout.columns 119 | let text = '' 120 | 121 | if (cols > 85) text = 'lets-build' 122 | else if (cols > 60) text = 'lets-|build' 123 | else text = false 124 | 125 | if (text && !isCI) { 126 | say(text, { 127 | colors: ['yellow'], 128 | font: 'simple3d', 129 | space: false 130 | }) 131 | } else console.log(chalk.yellow.bold('\n lets-build')) 132 | console.log() 133 | } -------------------------------------------------------------------------------- /.build-config/dev-client.js: -------------------------------------------------------------------------------- 1 | const hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 2 | 3 | hotClient.subscribe(event => { 4 | /** 5 | * Reload browser when HTMLWebpackPlugin emits a new index.html 6 | * 7 | * Currently disabled until jantimon/html-webpack-plugin#680 is resolved. 8 | * https://github.com/SimulatedGREG/electron-vue/issues/437 9 | * https://github.com/jantimon/html-webpack-plugin/issues/680 10 | */ 11 | // if (event.action === 'reload') { 12 | // window.location.reload() 13 | // } 14 | 15 | /** 16 | * Notify `mainWindow` when `main` process is compiling, 17 | * giving notice for an expected reload of the `electron` process 18 | */ 19 | if (event.action === 'compiling') { 20 | document.body.innerHTML += ` 21 | 34 | 35 |
36 | Compiling Main Process... 37 |
38 | ` 39 | } 40 | }) 41 | -------------------------------------------------------------------------------- /.build-config/dev-runner.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const chalk = require('chalk') 4 | const electron = require('electron') 5 | const path = require('path') 6 | const { say } = require('cfonts') 7 | const { spawn } = require('child_process') 8 | const webpack = require('webpack') 9 | const WebpackDevServer = require('webpack-dev-server') 10 | const webpackHotMiddleware = require('webpack-hot-middleware'); 11 | 12 | const mainConfig = require('./webpack.main.config') 13 | const rendererConfig = require('./webpack.renderer.config') 14 | 15 | let electronProcess = null 16 | let manualRestart = false 17 | let hotMiddleware 18 | 19 | function logStats (proc, data) { 20 | let log = '' 21 | 22 | log += chalk.yellow.bold(`┏ ${proc} Process ${new Array((19 - proc.length) + 1).join('-')}`) 23 | log += '\n\n' 24 | 25 | if (typeof data === 'object') { 26 | data.toString({ 27 | colors: true, 28 | chunks: false 29 | }).split(/\r?\n/).forEach(line => { 30 | log += ' ' + line + '\n' 31 | }) 32 | } else { 33 | log += ` ${data}\n` 34 | } 35 | 36 | log += '\n' + chalk.yellow.bold(`┗ ${new Array(28 + 1).join('-')}`) + '\n' 37 | 38 | console.log(log) 39 | } 40 | 41 | function startRenderer () { 42 | return new Promise((resolve, reject) => { 43 | rendererConfig.entry.renderer = [path.join(__dirname, 'dev-client')].concat(rendererConfig.entry.renderer) 44 | rendererConfig.mode = 'development' 45 | const compiler = webpack(rendererConfig) 46 | hotMiddleware = webpackHotMiddleware(compiler, { 47 | log: false, 48 | heartbeat: 2500 49 | }) 50 | 51 | compiler.hooks.compilation.tap('compilation', compilation => { 52 | compilation.hooks.htmlWebpackPluginAfterEmit.tapAsync('html-webpack-plugin-after-emit', (data, cb) => { 53 | hotMiddleware.publish({ action: 'reload' }) 54 | cb() 55 | }) 56 | }) 57 | 58 | compiler.hooks.done.tap('done', stats => { 59 | logStats('Renderer', stats) 60 | }) 61 | 62 | const server = new WebpackDevServer( 63 | compiler, 64 | { 65 | contentBase: path.join(__dirname, '../'), 66 | quiet: true, 67 | before (app, ctx) { 68 | app.use(hotMiddleware) 69 | ctx.middleware.waitUntilValid(() => { 70 | resolve() 71 | }) 72 | } 73 | } 74 | ) 75 | 76 | server.listen(9080) 77 | }) 78 | } 79 | 80 | function startMain () { 81 | return new Promise((resolve, reject) => { 82 | mainConfig.entry.main = [path.join(__dirname, '../src/main/index.dev.js')].concat(mainConfig.entry.main) 83 | mainConfig.mode = 'development' 84 | const compiler = webpack(mainConfig) 85 | 86 | compiler.hooks.watchRun.tapAsync('watch-run', (compilation, done) => { 87 | logStats('Main', chalk.white.bold('compiling...')) 88 | hotMiddleware.publish({ action: 'compiling' }) 89 | done() 90 | }) 91 | 92 | compiler.watch({}, (err, stats) => { 93 | if (err) { 94 | console.log(err) 95 | return 96 | } 97 | 98 | logStats('Main', stats) 99 | 100 | if (electronProcess && electronProcess.kill) { 101 | manualRestart = true 102 | process.kill(electronProcess.pid) 103 | electronProcess = null 104 | startElectron() 105 | 106 | setTimeout(() => { 107 | manualRestart = false 108 | }, 5000) 109 | } 110 | 111 | resolve() 112 | }) 113 | }) 114 | } 115 | 116 | function startElectron () { 117 | var args = [ 118 | '--inspect=5858', 119 | path.join(__dirname, '../dist/electron/main.js') 120 | ] 121 | 122 | // detect yarn or npm and process commandline args accordingly 123 | if (process.env.npm_execpath.endsWith('yarn.js')) { 124 | args = args.concat(process.argv.slice(3)) 125 | } else if (process.env.npm_execpath.endsWith('npm-cli.js')) { 126 | args = args.concat(process.argv.slice(2)) 127 | } 128 | 129 | electronProcess = spawn(electron, args) 130 | 131 | electronProcess.stdout.on('data', data => { 132 | electronLog(data, 'blue') 133 | }) 134 | electronProcess.stderr.on('data', data => { 135 | electronLog(data, 'red') 136 | }) 137 | 138 | electronProcess.on('close', () => { 139 | if (!manualRestart) process.exit() 140 | }) 141 | } 142 | 143 | function electronLog (data, color) { 144 | let log = '' 145 | data = data.toString().split(/\r?\n/) 146 | data.forEach(line => { 147 | log += ` ${line}\n` 148 | }) 149 | if (/[0-9A-z]+/.test(log)) { 150 | console.log( 151 | chalk[color].bold('┏ Electron -------------------') + 152 | '\n\n' + 153 | log + 154 | chalk[color].bold('┗ ----------------------------') + 155 | '\n' 156 | ) 157 | } 158 | } 159 | 160 | function greeting () { 161 | const cols = process.stdout.columns 162 | let text = '' 163 | 164 | if (cols > 104) text = 'electron-vue' 165 | else if (cols > 76) text = 'electron-|vue' 166 | else text = false 167 | 168 | if (text) { 169 | say(text, { 170 | colors: ['yellow'], 171 | font: 'simple3d', 172 | space: false 173 | }) 174 | } else console.log(chalk.yellow.bold('\n electron-vue')) 175 | console.log(chalk.blue(' getting ready...') + '\n') 176 | } 177 | 178 | function init () { 179 | greeting() 180 | 181 | Promise.all([startRenderer(), startMain()]) 182 | .then(() => { 183 | startElectron() 184 | }) 185 | .catch(err => { 186 | console.error(err) 187 | }) 188 | } 189 | 190 | init() 191 | -------------------------------------------------------------------------------- /.build-config/muti-page.config.js: -------------------------------------------------------------------------------- 1 | const glob = require('glob'); 2 | const path = require('path'); 3 | const PAGE_PATH = path.resolve(__dirname, '../src/renderer/page'); 4 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 5 | 6 | exports.entries = function () { 7 | /*用于匹配 pages 下一级文件夹中的 index.js 文件 */ 8 | var entryFiles = glob.sync(PAGE_PATH + '/*/main.js') 9 | var map = {} 10 | entryFiles.forEach((filePath) => { 11 | /* 下述两句代码用于取出 pages 下一级文件夹的名称 */ 12 | var entryPath = path.dirname(filePath) 13 | var filename = entryPath.substring(entryPath.lastIndexOf('\/') + 1) 14 | /* 生成对应的键值对 */ 15 | map[filename] = filePath 16 | }) 17 | return map 18 | } 19 | 20 | exports.htmlPlugin = function () { 21 | let entryHtml = glob.sync(PAGE_PATH + '/*/index.ejs') 22 | let arr = [] 23 | entryHtml.forEach((filePath) => { 24 | var entryPath = path.dirname(filePath) 25 | var filename = entryPath.substring(entryPath.lastIndexOf('\/') + 1) 26 | let conf = { 27 | template: filePath, 28 | filename: filename + `/index.html`, 29 | chunks: ['manifest', 'vendor', filename], 30 | inject: true, 31 | nodeModules: path.resolve(__dirname, '../node_modules'), 32 | templateParameters(compilation, assets, options) { 33 | return { 34 | // compilation: compilation, 35 | // webpack: compilation.getStats().toJson(), 36 | // webpackConfig: compilation.options, 37 | htmlWebpackPlugin: { 38 | files: assets, 39 | options: options 40 | }, 41 | process, 42 | } 43 | } 44 | } 45 | if (process.env.NODE_ENV === 'production') { 46 | let productionConfig = { 47 | minify: { 48 | removeComments: true, // 移除注释 49 | collapseWhitespace: true, // 删除空白符和换行符 50 | removeAttributeQuotes: true // 移除属性引号 51 | }, 52 | chunksSortMode: 'dependency' // 对引入的chunk模块进行排序 53 | } 54 | conf = {...conf, ...productionConfig} //合并基础配置和生产环境专属配置 55 | } 56 | arr.push(new HtmlWebpackPlugin(conf)) 57 | }) 58 | return arr 59 | } -------------------------------------------------------------------------------- /.build-config/webpack.main.config.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | process.env.BABEL_ENV = 'main' 4 | 5 | const path = require('path') 6 | const { dependencies } = require('../package.json') 7 | const webpack = require('webpack') 8 | 9 | const BabiliWebpackPlugin = require('babili-webpack-plugin') 10 | 11 | let mainConfig = { 12 | entry: { 13 | main: path.join(__dirname, '../src/main/index.js') 14 | }, 15 | externals: [ 16 | ...Object.keys(dependencies || {}) 17 | ], 18 | module: { 19 | rules: [ 20 | // { 21 | // test: /\.(js)$/, 22 | // enforce: 'pre', 23 | // exclude: /node_modules/, 24 | // use: { 25 | // loader: 'eslint-loader', 26 | // options: { 27 | // formatter: require('eslint-friendly-formatter') 28 | // } 29 | // } 30 | // }, 31 | { 32 | test: /\.js$/, 33 | use: 'babel-loader', 34 | exclude: /node_modules/ 35 | }, 36 | { 37 | test: /\.node$/, 38 | use: 'node-loader' 39 | } 40 | ] 41 | }, 42 | node: { 43 | __dirname: process.env.NODE_ENV !== 'production', 44 | __filename: process.env.NODE_ENV !== 'production' 45 | }, 46 | output: { 47 | filename: '[name].js', 48 | libraryTarget: 'commonjs2', 49 | path: path.join(__dirname, '../dist/electron') 50 | }, 51 | plugins: [ 52 | new webpack.NoEmitOnErrorsPlugin() 53 | ], 54 | resolve: { 55 | extensions: ['.js', '.json', '.node'] 56 | }, 57 | target: 'electron-main' 58 | } 59 | 60 | /** 61 | * Adjust mainConfig for development settings 62 | */ 63 | if (process.env.NODE_ENV !== 'production') { 64 | mainConfig.plugins.push( 65 | new webpack.DefinePlugin({ 66 | '__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"` 67 | }) 68 | ) 69 | } 70 | 71 | /** 72 | * Adjust mainConfig for production settings 73 | */ 74 | if (process.env.NODE_ENV === 'production') { 75 | mainConfig.plugins.push( 76 | new BabiliWebpackPlugin(), 77 | new webpack.DefinePlugin({ 78 | 'process.env.NODE_ENV': '"production"' 79 | }) 80 | ) 81 | } 82 | 83 | module.exports = mainConfig 84 | -------------------------------------------------------------------------------- /.build-config/webpack.renderer.config.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | process.env.BABEL_ENV = 'renderer' 4 | 5 | const path = require('path') 6 | const { dependencies } = require('../package.json') 7 | const webpack = require('webpack') 8 | 9 | const BabiliWebpackPlugin = require('babili-webpack-plugin') 10 | const CopyWebpackPlugin = require('copy-webpack-plugin') 11 | const MiniCssExtractPlugin = require('mini-css-extract-plugin') 12 | const HtmlWebpackPlugin = require('html-webpack-plugin') 13 | const { VueLoaderPlugin } = require('vue-loader') 14 | const {entries, htmlPlugin} = require('./muti-page.config'); 15 | /** 16 | * List of node_modules to include in webpack bundle 17 | * 18 | * Required for specific packages like Vue UI libraries 19 | * that provide pure *.vue files that need compiling 20 | * https://simulatedgreg.gitbooks.io/electron-vue/content/en/webpack-configurations.html#white-listing-externals 21 | */ 22 | let whiteListedModules = ['vue'] 23 | console.log() 24 | let rendererConfig = { 25 | devtool: '#cheap-module-eval-source-map', 26 | // entry: { 27 | // renderer: path.join(__dirname, '../src/renderer/main.js') 28 | // }, 29 | entry: entries, 30 | externals: [ 31 | ...Object.keys(dependencies || {}).filter(d => !whiteListedModules.includes(d)) 32 | ], 33 | module: { 34 | rules: [ 35 | // { 36 | // test: /\.(js|vue)$/, 37 | // enforce: 'pre', 38 | // exclude: /node_modules/, 39 | // use: { 40 | // loader: 'eslint-loader', 41 | // options: { 42 | // formatter: require('eslint-friendly-formatter') 43 | // } 44 | // } 45 | // }, 46 | { 47 | test: /\.scss$/, 48 | use: ['vue-style-loader', 'css-loader', 'sass-loader'] 49 | }, 50 | { 51 | test: /\.sass$/, 52 | use: ['vue-style-loader', 'css-loader', 'sass-loader?indentedSyntax'] 53 | }, 54 | { 55 | test: /\.less$/, 56 | use: ['vue-style-loader', 'css-loader', 'less-loader'] 57 | }, 58 | { 59 | test: /\.css$/, 60 | use: ['vue-style-loader', 'css-loader'] 61 | }, 62 | { 63 | test: /\.html$/, 64 | use: 'vue-html-loader' 65 | }, 66 | { 67 | test: /\.js$/, 68 | use: 'babel-loader', 69 | exclude: /node_modules/ 70 | }, 71 | { 72 | test: /\.node$/, 73 | use: 'node-loader' 74 | }, 75 | { 76 | test: /\.vue$/, 77 | use: { 78 | loader: 'vue-loader', 79 | options: { 80 | extractCSS: process.env.NODE_ENV === 'production', 81 | loaders: { 82 | sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1', 83 | scss: 'vue-style-loader!css-loader!sass-loader', 84 | less: 'vue-style-loader!css-loader!less-loader' 85 | } 86 | } 87 | } 88 | }, 89 | { 90 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 91 | use: { 92 | loader: 'url-loader', 93 | query: { 94 | limit: 10000, 95 | name: 'imgs/[name]--[folder].[ext]', 96 | fallback: 'file-loader', 97 | outputPath: './', 98 | publicPath: '../' 99 | } 100 | } 101 | }, 102 | { 103 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, 104 | loader: 'url-loader', 105 | options: { 106 | limit: 10000, 107 | name: 'media/[name]--[folder].[ext]' 108 | } 109 | }, 110 | { 111 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 112 | use: { 113 | loader: 'url-loader', 114 | query: { 115 | limit: 10000, 116 | name: 'fonts/[name]--[folder].[ext]' 117 | } 118 | } 119 | } 120 | ] 121 | }, 122 | node: { 123 | __dirname: process.env.NODE_ENV !== 'production', 124 | __filename: process.env.NODE_ENV !== 'production' 125 | }, 126 | plugins: [ 127 | new VueLoaderPlugin(), 128 | new MiniCssExtractPlugin({filename: 'styles.css'}), 129 | // new HtmlWebpackPlugin({ 130 | // filename: 'index.html', 131 | // template: path.resolve(__dirname, '../src/index.ejs'), 132 | // minify: { 133 | // collapseWhitespace: true, 134 | // removeAttributeQuotes: true, 135 | // removeComments: true 136 | // }, 137 | // nodeModules: path.resolve(__dirname, '../node_modules') 138 | // // process.env.NODE_ENV !== 'production' 139 | // // ? path.resolve(__dirname, '../node_modules') 140 | // // : false 141 | // }), 142 | new webpack.HotModuleReplacementPlugin(), 143 | new webpack.NoEmitOnErrorsPlugin() 144 | ].concat(htmlPlugin()), 145 | output: { 146 | filename: '[name]/index.js', 147 | libraryTarget: 'commonjs2', 148 | path: path.join(__dirname, '../dist/electron') 149 | }, 150 | resolve: { 151 | alias: { 152 | '@': path.join(__dirname, '../src/renderer'), 153 | 'vue$': 'vue/dist/vue.esm.js' 154 | }, 155 | extensions: ['.js', '.vue', '.json', '.css', '.node'] 156 | }, 157 | target: 'electron-renderer' 158 | } 159 | 160 | /** 161 | * Adjust rendererConfig for development settings 162 | */ 163 | if (process.env.NODE_ENV !== 'production') { 164 | rendererConfig.plugins.push( 165 | new webpack.DefinePlugin({ 166 | '__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"` 167 | }) 168 | ) 169 | } 170 | 171 | /** 172 | * Adjust rendererConfig for production settings 173 | */ 174 | if (process.env.NODE_ENV === 'production') { 175 | rendererConfig.devtool = '' 176 | 177 | rendererConfig.plugins.push( 178 | new BabiliWebpackPlugin(), 179 | new CopyWebpackPlugin([ 180 | { 181 | from: path.join(__dirname, '../static'), 182 | to: path.join(__dirname, '../dist/electron/static'), 183 | ignore: ['.*'] 184 | } 185 | ]), 186 | new webpack.DefinePlugin({ 187 | 'process.env.NODE_ENV': '"production"' 188 | }), 189 | new webpack.LoaderOptionsPlugin({ 190 | minimize: true 191 | }) 192 | ); 193 | } 194 | 195 | module.exports = rendererConfig 196 | -------------------------------------------------------------------------------- /.build-config/webpack.web.config.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | process.env.BABEL_ENV = 'web' 4 | 5 | const path = require('path') 6 | const webpack = require('webpack') 7 | 8 | const BabiliWebpackPlugin = require('babili-webpack-plugin') 9 | const CopyWebpackPlugin = require('copy-webpack-plugin') 10 | const MiniCssExtractPlugin = require('mini-css-extract-plugin') 11 | const HtmlWebpackPlugin = require('html-webpack-plugin') 12 | const { VueLoaderPlugin } = require('vue-loader') 13 | 14 | let webConfig = { 15 | devtool: '#cheap-module-eval-source-map', 16 | entry: { 17 | web: path.join(__dirname, '../src/renderer/main.js') 18 | }, 19 | module: { 20 | rules: [ 21 | // { 22 | // test: /\.(js|vue)$/, 23 | // enforce: 'pre', 24 | // exclude: /node_modules/, 25 | // use: { 26 | // loader: 'eslint-loader', 27 | // options: { 28 | // formatter: require('eslint-friendly-formatter') 29 | // } 30 | // } 31 | // }, 32 | { 33 | test: /\.scss$/, 34 | use: ['vue-style-loader', 'css-loader', 'sass-loader'] 35 | }, 36 | { 37 | test: /\.sass$/, 38 | use: ['vue-style-loader', 'css-loader', 'sass-loader?indentedSyntax'] 39 | }, 40 | { 41 | test: /\.less$/, 42 | use: ['vue-style-loader', 'css-loader', 'less-loader'] 43 | }, 44 | { 45 | test: /\.css$/, 46 | use: ['vue-style-loader', 'css-loader'] 47 | }, 48 | { 49 | test: /\.html$/, 50 | use: 'vue-html-loader' 51 | }, 52 | { 53 | test: /\.js$/, 54 | use: 'babel-loader', 55 | include: [ path.resolve(__dirname, '../src/renderer') ], 56 | exclude: /node_modules/ 57 | }, 58 | { 59 | test: /\.vue$/, 60 | use: { 61 | loader: 'vue-loader', 62 | options: { 63 | extractCSS: true, 64 | loaders: { 65 | sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1', 66 | scss: 'vue-style-loader!css-loader!sass-loader', 67 | less: 'vue-style-loader!css-loader!less-loader' 68 | } 69 | } 70 | } 71 | }, 72 | { 73 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 74 | use: { 75 | loader: 'url-loader', 76 | query: { 77 | limit: 10000, 78 | name: 'imgs/[name].[ext]' 79 | } 80 | } 81 | }, 82 | { 83 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 84 | use: { 85 | loader: 'url-loader', 86 | query: { 87 | limit: 10000, 88 | name: 'fonts/[name].[ext]' 89 | } 90 | } 91 | } 92 | ] 93 | }, 94 | plugins: [ 95 | new VueLoaderPlugin(), 96 | new MiniCssExtractPlugin({filename: 'styles.css'}), 97 | new HtmlWebpackPlugin({ 98 | filename: 'index.html', 99 | template: path.resolve(__dirname, '../src/index.ejs'), 100 | minify: { 101 | collapseWhitespace: true, 102 | removeAttributeQuotes: true, 103 | removeComments: true 104 | }, 105 | nodeModules: false 106 | }), 107 | new webpack.DefinePlugin({ 108 | 'process.env.IS_WEB': 'true' 109 | }), 110 | new webpack.HotModuleReplacementPlugin(), 111 | new webpack.NoEmitOnErrorsPlugin() 112 | ], 113 | output: { 114 | filename: '[name].js', 115 | path: path.join(__dirname, '../dist/web') 116 | }, 117 | resolve: { 118 | alias: { 119 | '@': path.join(__dirname, '../src/renderer'), 120 | 'vue$': 'vue/dist/vue.esm.js' 121 | }, 122 | extensions: ['.js', '.vue', '.json', '.css'] 123 | }, 124 | target: 'web' 125 | } 126 | 127 | /** 128 | * Adjust webConfig for production settings 129 | */ 130 | if (process.env.NODE_ENV === 'production') { 131 | webConfig.devtool = '' 132 | 133 | webConfig.plugins.push( 134 | new BabiliWebpackPlugin(), 135 | new CopyWebpackPlugin([ 136 | { 137 | from: path.join(__dirname, '../static'), 138 | to: path.join(__dirname, '../dist/web/static'), 139 | ignore: ['.*'] 140 | } 141 | ]), 142 | new webpack.DefinePlugin({ 143 | 'process.env.NODE_ENV': '"production"' 144 | }), 145 | new webpack.LoaderOptionsPlugin({ 146 | minimize: true 147 | }) 148 | ) 149 | } 150 | 151 | module.exports = webConfig 152 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shenX-2021/vue-electron-muti-page/2d442920bcc856969c15ccdad048ce618b87af8f/.eslintignore -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: 'babel-eslint', 4 | parserOptions: { 5 | sourceType: 'module' 6 | }, 7 | env: { 8 | browser: true, 9 | node: true 10 | }, 11 | extends: 'airbnb-base', 12 | globals: { 13 | __static: true 14 | }, 15 | plugins: [ 16 | 'html' 17 | ], 18 | 'rules': { 19 | 'comma-dangle': 0, 20 | 'global-require': 0, 21 | 'import/no-unresolved': 0, 22 | 'no-param-reassign': 0, 23 | 'no-shadow': 0, 24 | 'import/extensions': 0, 25 | 'import/newline-after-import': 0, 26 | 'no-multi-assign': 0, 27 | // allow debugger during development 28 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | dist/electron/*/ 3 | dist/electron/main.js 4 | dist/web/* 5 | build/* 6 | !build/icons 7 | node_modules/ 8 | npm-debug.log 9 | npm-debug.log.* 10 | thumbs.db 11 | !.gitkeep 12 | 13 | 14 | # dist 15 | # dist/ 16 | 17 | # package-lock.json 18 | package-lock.json 19 | -------------------------------------------------------------------------------- /.idea/Shorthands_PC.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 77 | 78 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | true 91 | DEFINITION_ORDER 92 | 93 | 94 | 95 | 96 | 97 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 |