導航:
(一)Electron跑起來
(二)從零搭建Vue全家桶+webpack項目框架
(三)Electron+Vue+Webpack,聯合調試整個項目
(四)Electron配置潤色
(五)預加載及自動更新
(六)構建、發布整個項目(包括client和web)
摘要:前面兩篇介紹了如何啟動Electron和Vue項目,但到目前為止,雖然把Electron和Vue放到了一個工程里,但貌似它們之間並沒有什么關系,通過不同的命令各自運行,Vue寫出的頁面也無法在Electron中展示,這跟我們的標題顯然是不符合的。先喊個口號,從我做起,拒絕標題黨!這篇就說一下,如何把Electron和Vue通過Webpack結合起來。項目完整代碼:https://github.com/luohao8023/electron-vue-template
一、新建webpack.main.config.js,webpack打包electron的常規配置。
const path=require('path');
const webpack = require('webpack');
const { dependencies } = require('../package.json');
module.exports = {
mode: process.env.NODE_ENV,
entry: {
main: ['./src/main/main.js'],
},
output: {
path: path.join(process.cwd(), 'app'),
libraryTarget: 'commonjs2',
filename: './[name].js'
},
node: {
fs: 'empty',
__dirname: false
},
optimization: {
runtimeChunk: false,
minimize: true
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
}
]
},
externals: [
...Object.keys(dependencies || {})
],
resolve: {
extensions: ['.js']
},
plugins:[
new webpack.NoEmitOnErrorsPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': '"production"'
})
],
target: 'electron-main'
};
二、改造dev.js,主體思路是打包主進程、打包渲染進程,啟動electron應用。
process.env.NODE_ENV = 'development';//開發模式 const webpack = require('webpack'); const WebpackDevServer = require('webpack-dev-server'); const webpackHotMiddleware = require('webpack-hot-middleware'); const chalk = require('chalk'); const http = require('http'); const { spawn } = require('child_process'); const electron = require('electron'); const path = require('path'); // 構建主進程 function buildMain() { const mainWebpackConfig = require('./webpack.main.config.js'); return new Promise((resolve, reject) => { console.log('打包APP主進程......'); let log = ''; // 刪除歷史打包數據 require('del')(['./app/main.js']); const mainCompiler = webpack(mainWebpackConfig); mainCompiler.run((err, stats) => { let errorInfo = ''; if (err) { console.log('打包主進程遇到Error!'); reject(chalk.red(err)); } else { Object.keys(stats.compilation.assets).forEach(key => { log += chalk.blue(key) + '\n'; }) stats.compilation.warnings.forEach(key => { log += chalk.yellow(key) + '\n'; }) stats.compilation.errors.forEach(key => { errorInfo += chalk.red(`${key}:${stats.compilation.errors[key]}`) + '\n'; }) log += errorInfo+ chalk.green(`time:${(stats.endTime-stats.startTime)/1000} s\n`) + "\n"; if(errorInfo){ reject(errorInfo) }else{ resolve(log); } console.log('打包主進程完畢!', log); } }); }); } // 構建渲染進程 function devRender() { console.log('啟動渲染進程調試......'); const webpackDevConfig = require('./webpack.render.config.js'); const compiler = webpack(webpackDevConfig); new WebpackDevServer( compiler, { contentBase: webpackDevConfig.output.path, publicPath: webpackDevConfig.output.publicPath, open: true,//打開默認瀏覽器 inline: true,//刷新模式 hot: true,//熱更新 quiet: true,//除第一次編譯外,其余不顯示編譯信息 progress: true,//顯示打包進度 setup(app) { app.use(webpackHotMiddleware(compiler)); app.use('*', (req, res, next) => { if (String(req.originalUrl).indexOf('.html') > 0) { console.log(req.originalUrl) getHtml(res); } else { next(); } }); } } ).listen(8099, function(err) { if (err) return console.log(err); console.log(`Listening at http://localhost:8099`); }); compiler.hooks.done.tap('doneCallback', (stats) => { const compilation = stats.compilation; Object.keys(compilation.assets).forEach(key => console.log(chalk.blue(key))); compilation.warnings.forEach(key => console.log(chalk.yellow(key))); compilation.errors.forEach(key => console.log(chalk.red(`${key}:${stats.compilation.errors[key]}`))); console.log(chalk.green(`${chalk.white('渲染進程調試完畢\n')}time:${(stats.endTime-stats.startTime)/1000} s`)); }); } // 啟動Electron function startElectron() { let electronProcess = spawn(electron, [path.join(process.cwd(), 'app/main.js')]); electronProcess.stdout.on('data', data => { // 正常輸出為藍色 electronLog(data, 'blue'); }); electronProcess.stderr.on('data', data => { // 錯誤信息為紅色 electronLog(data, 'red'); }); } // 美化輸出 function electronLog(data, color) { let log = ''; data.toString().split(/\r?\n/).forEach(line => { log += `\n${line}`; }); if (/[0-9A-z]+/.test(log)) { console.log( chalk[color].bold('┏ Electron -------------------') + log + chalk[color].bold('┗ ----------------------------') ); } } function getHtml(res) { http.get(`http://localhost:8099`, (response) => { response.pipe(res); }).on('error', (err) => { console.log(err); }); } // 構建 function build() { Promise.all([buildMain(), devRender()]).then(() => { startElectron(); }).catch(err => { console.log(err); process.exit(); }); } build();
運行npm run dev,迎接即將出現的各種錯誤吧!以下不是運行一次時出現的錯誤,而是每次解決完報錯之后默認運行一次。
1、找不到babel-loader,這個簡單,裝一個就行了,npm i babel-loader -D。
2、看樣子是babel-loader還需要其他依賴,按提示安裝,npm i @babel/core -D。

3、直接打開了瀏覽器有木有?!!在dev.js中62行,把打開默認瀏覽器的選項設為false,即open:false。
4、再運行,electron可以正常打開了,但顯示但內容卻不對,無論怎么修改vue文件重新運行,都不會起作用。找到src/main/main.js,把
win.loadURL(encodeURI(indexPath));
這一行改為
win.loadURL('http://localhost:8099');
發現之前代碼的一個錯誤,win變量是在createWindow函數中聲明但,但在函數外部卻有調用,修改一下。
再次運行,可以正常啟動,而且顯示的是vue文件中的內容,嘗試修改一下頁面內容,熱刷新也是正常的。
至此,我們已經可以正常的進行本地開發調試了,再說一下大致的思路:
第一篇和第二篇主要是把完整的Electron項目和Vue項目融合到一個工程里,本篇主要是增加了主進程的webpack配置,並改造了dev.js,在這個腳本中主要做了下面的事:啟動渲染進程的打包(這里是devServer),打包主進程,以main.js為入口,輸出位置為app文件夾,之后用node的spawn模塊,以electron命令執行app文件夾下的main.js,啟動electron,並把electron的頁面地址只想devServer地址,這就是本地調試的大致邏輯了。文字不太多,主要是理解webpack配置及調試腳本。后面會介紹到構建整個項目,並打包exe安裝文件,以及其他的一些配置優化、項目結構優化。
