构建Electron应用

前面的话

Electron可以让我们使用web开发的技术去开发跨平台的桌面端应用,我们熟悉的VSCode编译器就是使用Electron开发的。这篇文章介绍如何将Electron接入webpack。

主进程

  • 启动一个electron应用从一个主进程开始。主进程的启动通过一个JavaScript入口文件实现的。
  • 主进程启动后会一直驻留在后台运行,我们操作的窗口并不是主进程,而是由主进程新启动的窗口子进程
  • 每一个窗口都是一个单独的网页进程,窗口之间需要借助主进程传递消息。

通过命令 npm init 生成的package.json文件中的main.js就是electron的一个主进程:
在这里插入图片描述

在man.js文件中写入下面的内容:

const { app, BrowserWindow } = require('electron')

// 保持对window对象的全局引用,如果不这么做的话,当JavaScript对象被
// 垃圾回收的时候,window对象将会自动的关闭
let win

function createWindow () {
  // 创建浏览器窗口。
  win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
    }
  })

  // 加载index.html文件
  const indexPageURL = `./dist/index.html`;

  win.loadFile(indexPageURL)

  // 打开开发者工具
  win.webContents.openDevTools()

  // 当 window 被关闭,这个事件会被触发。
  win.on('closed', () => {
    // 取消引用 window 对象,如果你的应用支持多窗口的话,
    // 通常会把多个 window 对象存放在一个数组里面,
    // 与此同时,你应该删除相应的元素。
    win = null
  })
}

// Electron 会在初始化后并准备
// 创建浏览器窗口时,调用这个函数。
// 部分 API 在 ready 事件触发后才能使用。
app.on('ready', createWindow)

// 当全部窗口关闭时退出。
app.on('window-all-closed', () => {
  // 在 macOS 上,除非用户用 Cmd + Q 确定地退出,
  // 否则绝大部分应用及其菜单栏会保持激活。
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  // 在macOS上,当单击dock图标并且没有其他窗口打开时,
  // 通常在应用程序中重新创建一个窗口。
  if (win === null) {
    createWindow()
  }
})

注意: electron升级到5.0系列之后,如果不加上下面的代码就会报出require is not defined的错误,这是因为浏览器本生是不支持require。而5.0将以前版本默认的 nodeIntegration: true改为了false,所以我们要手动开启。

 webPreferences: {
        nodeIntegration: true,  // 解决require is not defined问题
        webviewTag: true  // 解决webview无法显示问题
   }    

主进程中打开了一个dis目录下的index.html文件,这是使用webpack自动生成的页面,前面的文章已经介绍过,这里不过多解释。

接入webpack

一个简单的Electron应用,要求在启动后显示一个主窗口,在主窗口里面有一个按钮,点击这个按钮会重新显示一个窗口。

这个例子是基于前面的管理多个页面中的列子来实现的,这里创建了两个页面,一个主窗口,一个login窗口。

在这里插入图片描述
使用插件AutoWebPlugin可以自动生成相应的index.html与login.html。(前面已经介绍过)。

在index.js中:创建一个点击按钮,并且点击之后生成一个新的登录窗口:

import React, { Component } from 'react';
import { render } from 'react-dom';
import { remote } from 'electron';
import path from 'path';
import './index.css';

class App extends Component {

  // 在按钮被点击时
  handleBtnClick() {
    // 新窗口对应的页面的 URI 地址
    const modalPath = path.join('file://', remote.app.getAppPath(), 'dist/login.html');
    // 新窗口的大小
    let win = new remote.BrowserWindow({ 
      width: 400, 
      height: 320,
      webPreferences: {
        nodeIntegration: true,  // 解决require is not defined问题
        webviewTag: true  // 解决webview无法显示问题
      }    
     })
    win.on('close', function () {
      // 窗口被关闭时清空资源
      win = null
    })
    // 加载网页
    win.loadURL(modalPath);
    // 显示窗口
    win.show()
  }

  render() {
    return (
      <div>
        <h1>Page Index</h1>
        <button onClick={this.handleBtnClick}>Open Page Login</button>
      </div>
    )
  }
}

render(<App/>, window.document.getElementById('app'));

webpack配置文件:

const path = require('path');
const { AutoWebPlugin } = require('web-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

// 使用AutoWebPlugin自动寻找pages目录下的所有目录,将每一个目录看成一个单页应用
const autoWebPlugin  = new AutoWebPlugin('page', {
    template: './template.html', // HTML模板文件所在的文件路径
    postEntrys:['./common.css'],// 所有的页面都依赖的共用的css样式文件
    // 提取所有页面的公共代码
    commonsChunk: { 
        name: 'common'// 提取出公共代码的Chunk名称
    }
});
module.exports = {
    // AutoWebPlugin会为寻找到的所有单页应用生成对应的入口配置
    // autoWebPlugin.entry方法可以获取所有由autoWebPlugin生成的入口配置
    entry: autoWebPlugin.entry({
    }),
    // 构建出用于 Electron 渲染进程用的 JavaScript 代码,也就是这2个窗口需要的代码
    target: 'electron-renderer',
    output:{
        filename: '[name]_[chunkhash:8].js',
        path: path.resolve(__dirname, './dist'),
    },


    module: {
        rules: [
            {
                test: /\.js$/,
                use:['babel-loader'],
                exclude: path.resolve(__dirname, 'node_modules'),
            },
            {
                test: /\.css/,
                use: [
                     MiniCssExtractPlugin.loader,
                     'css-loader'
                ]
            }
        ]
    },
    plugins: [
        autoWebPlugin,
        new MiniCssExtractPlugin({
            filename: '[name]_[contenthash:8].css'
        })
    ]   
}

完成这两个页面相应的代码之后,由于webpack内置支持electon,只需要在Webpackp配置文件中加一行代码:

target:'electron-renderer',

运行项目

完整的项目地址: electron

$ npm install
$ webpack
$ npm start

在这里插入图片描述

发布了238 篇原创文章 · 获赞 175 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_41257129/article/details/103678974