【原創】從零開始搭建Electron+Vue+Webpack項目框架(三)Electron+vue+webpack聯合調試

導航:html

(一)Electron跑起來
(二)從零搭建Vue全家桶+webpack項目框架
(三)Electron+Vue+Webpack,聯合調試整個項目
(四)Electron配置潤色
(五)預加載及自動更新
(六)構建、發佈整個項目(包括client和web)(未完待續)vue

摘要:前面兩篇介紹瞭如何啓動Electron和Vue項目,但到目前爲止,雖然把Electron和Vue放到了一個工程裏,但貌似它們之間並無什麼關係,經過不一樣的命令各自運行,Vue寫出的頁面也沒法在Electron中展現,這跟咱們的標題顯然是不符合的。先喊個口號,從我作起,拒絕標題黨!這篇就說一下,如何把Electron和Vue經過Webpack結合起來。項目完整代碼:https://github.com/luohao8023/electron-vue-templatenode

1、新建webpack.main.config.js,webpack打包electron的常規配置。webpack

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'
};

2、改造dev.js,主體思路是打包主進程、打包渲染進程,啓動electron應用。git

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,迎接即將出現的各類錯誤吧!如下不是運行一次時出現的錯誤,而是每次解決完報錯以後默認運行一次。github

一、找不到babel-loader,這個簡單,裝一個就好了,npm i babel-loader -D。web

二、看樣子是babel-loader還須要其餘依賴,按提示安裝,npm i @babel/core -D。npm

三、直接打開了瀏覽器有木有?!!在dev.js中62行,把打開默認瀏覽器的選項設爲false,即open:false。json

四、再運行,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安裝文件,以及其餘的一些配置優化、項目結構優化。

相關文章
相關標籤/搜索