• 【原创】从零开始搭建Electron+Vue+Webpack项目框架(三)Electron+vue+webpack联合调试


    导航:

    (一)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) + '
    ';
                    })
                    stats.compilation.warnings.forEach(key => {
                        log += chalk.yellow(key) + '
    ';
                    })
                    stats.compilation.errors.forEach(key => {
                        errorInfo += chalk.red(`${key}:${stats.compilation.errors[key]}`) + '
    ';
                    })
                    log += errorInfo+ chalk.green(`time:${(stats.endTime-stats.startTime)/1000} s
    `) + "
    ";
                    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('渲染进程调试完毕
    ')}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(/
    ?
    /).forEach(line => {
            log += `
    ${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安装文件,以及其他的一些配置优化、项目结构优化。

  • 相关阅读:
    组件定义
    序列化代码
    Views 代码 导包
    DRF 初始化
    Urls 代码
    怎么用sublime text 3搭建python 的ide
    C语言位运算
    ZOJ 1104 Leaps Tall Buildings
    UVa 10739 String to Palindrome
    ZOJ 3563 Alice's Sequence II
  • 原文地址:https://www.cnblogs.com/kakayang/p/12084993.html
Copyright © 2020-2023  润新知