1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 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 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 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 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
| 'use strict' const chalk = require('chalk') const electron = require('electron') const path = require('path') const { say } = require('cfonts') const { spawn } = require('child_process') const webpack = require('webpack') const WebpackDevServer = require('webpack-dev-server') const webpackHotMiddleware = require('webpack-hot-middleware') const mainConfig = require('./webpack.main.config') const rendererConfig = require('./webpack.renderer.config') let electronProcess = null let manualRestart = false let hotMiddleware function logStats (proc, data) { let log = '' log += chalk.yellow.bold(`┏ ${proc} Process ${new Array((19 - proc.length) + 1).join('-')}`) log += '\n\n' if (typeof data === 'object') { data.toString({ colors: true, chunks: false }).split(/\r?\n/).forEach(line => { log += ' ' + line + '\n' }) } else { log += ` ${data}\n` } log += '\n' + chalk.yellow.bold(`┗ ${new Array(28 + 1).join('-')}`) + '\n' console.log(log) } // 启动渲染进程 // 整体作用:将dev-client.js和renderer/main.js合并到webpack entry字段,输出到根目录下的/dist/electron/main.js文件中 function startRenderer () { // 加载webpack配置 return new Promise((resolve, reject) => { rendererConfig.entry.renderer = [path.join(__dirname, 'dev-client')].concat(rendererConfig.entry.renderer) rendererConfig.mode = 'development' // 创建webpack const compiler = webpack(rendererConfig) // 创建webpack热加载 // webpackHotMiddleware的heartbeat的参数作用并不是检测文件的频率,而是保持服务器链接存活的心跳频率 hotMiddleware = webpackHotMiddleware(compiler, { log: false, heartbeat: 2500 }) // 编译状态监控 # 监听的是 compilation事件 compiler.hooks.compilation.tap('compilation', compilation => { compilation.hooks.htmlWebpackPluginAfterEmit.tapAsync('html-webpack-plugin-after-emit', (data, cb) => { // 钩子函数,检测webpack的编译状态,把其中的html-webpack-plugin-after-emit状态,发布到webpackHotMiddleware中 hotMiddleware.publish({ action: 'reload' }) cb() }) }) // 输出打包编译过程 compiler.hooks.done.tap('done', stats => { logStats('Renderer', stats) }) // 创建webpack-dev-server const server = new WebpackDevServer( compiler, { contentBase: path.join(__dirname, '../'), quiet: true, before (app, ctx) { // 使用webpackHotMiddleware app.use(hotMiddleware) ctx.middleware.waitUntilValid(() => { resolve() }) } } ) // 监听窗口 server.listen(9080) }) } // 启动主进程 - 过程与渲染进程是类似的 // 创建webpack,实时发布hotMiddleware,主代码热更新 function startMain () { // 导入index.dev.js,该文件主要安装electron-debug工具,同时也安装了vue-devtools工具 // webpack.config.main.js与render相比,main不需要去去处理vue,图片, css,html等,只需要对js处理 return new Promise((resolve, reject) => { mainConfig.entry.main = [path.join(__dirname, '../src/main/index.dev.js')].concat(mainConfig.entry.main) mainConfig.mode = 'development' // 创建主进程的 webpack const compiler = webpack(mainConfig) # 监听的是watch-run事件 compiler.hooks.watchRun.tapAsync('watch-run', (compilation, done) => { logStats('Main', chalk.white.bold('compiling...')) hotMiddleware.publish({ action: 'compiling' }) done() }) // 与render不同,没有使用WebpackDevServer的方式自动更新界面,而是通过webpack的watch模式,不断重新启动程序,类似于electron-forge start compiler.watch({}, (err, stats) => { if (err) { console.log(err) return } logStats('Main', stats) if (electronProcess && electronProcess.kill) { manualRestart = true process.kill(electronProcess.pid) electronProcess = null // 重新启动项目 startElectron() setTimeout(() => { manualRestart = false }, 5000) } resolve() }) }) } // 启动electron function startElectron () { var args = [ '--inspect=5858', path.join(__dirname, '../dist/electron/main.js') ] // detect yarn or npm and process commandline args accordingly if (process.env.npm_execpath.endsWith('yarn.js')) { args = args.concat(process.argv.slice(3)) } else if (process.env.npm_execpath.endsWith('npm-cli.js')) { args = args.concat(process.argv.slice(2)) } // 创建主进程执行特别命令 electronProcess = spawn(electron, args) electronProcess.stdout.on('data', data => { electronLog(data, 'blue') }) electronProcess.stderr.on('data', data => { electronLog(data, 'red') }) electronProcess.on('close', () => { if (!manualRestart) process.exit() }) } function electronLog (data, color) { let log = '' data = data.toString().split(/\r?\n/) data.forEach(line => { log += ` ${line}\n` }) if (/[0-9A-z]+/.test(log)) { console.log( chalk[color].bold('┏ Electron -------------------') + '\n\n' + log + chalk[color].bold('┗ ----------------------------') + '\n' ) } } // electron-vue Log输出 function greeting () { const cols = process.stdout.columns let text = '' if (cols > 104) text = 'electron-vue' else if (cols > 76) text = 'electron-|vue' else text = false if (text) { say(text, { colors: ['yellow'], font: 'simple3d', space: false }) } else console.log(chalk.yellow.bold('\n electron-vue')) console.log(chalk.blue(' getting ready...') + '\n') } // 初始函数 function init () { greeting() // 主进程和渲染进程都启动完毕 Promise.all([startRenderer(), startMain()]) .then(() => { startElectron() }) .catch(err => { console.error(err) }) } init()
|