【前端记事】关于electron的入门使用

electron入门使用

背景

最近对electron比较感兴趣,折腾一段时间后有了点眉目,记录一下

how to start

第一步 创建一个vite-vue3项目

bash 复制代码
# 选vue3但是不要用ts,用js会舒服得多
npm create vite -n test-electron

第二步 装各种依赖

bash 复制代码
# 命令1
npm i electron -d -s
# 命令2
npm install vite-plugin-optimizer --save-dev
# 命令3
npm install vite-plugin-node-polyfills --save-dev
# 命令4
npm install @electron/remote
# 命令5
npm install element-plus --save
# 命令6
npm i vue-router

注意,命令1可能需要反复执行反复失败才会成功,推测是网的原因,而且我自己测试用yarn和pnpm必报错,只有npm才行

第三步 配置

vite.config.js

js 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { nodePolyfills } from 'vite-plugin-node-polyfills'
import optimizer from 'vite-plugin-optimizer'

// https://vite.dev/config/
export default defineConfig({
  plugins: [
    vue(), // 添加 Node.js 内置模块的 polyfill
    nodePolyfills({
      include: ['path'],
      globals: { Buffer: true, global: true, process: true },
      protocolImports: true,
    }),
    optimizer({
      electron: `const { ipcRenderer } = require('electron'); export { ipcRenderer };`
    })
  ],
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          // 将第三方库分割到单独的代码块
          'vendor': ['element-plus'],
        }
      }
    }
  },
  server: {
    port: 8888,
    cors: true, // 允许跨域
    hmr: true, // 开启热更新
  },
  "base": "./"
})

package.json

json 复制代码
{
  "name": "ele-pro",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "main": "electron/main.cjs",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview",
    "electron:serve": "vite build && electron ."
  },
  "dependencies": {
    "@electron/remote": "^2.1.2",
    "electron-reload": "^2.0.0-alpha.1",
    "element-plus": "^2.9.7",
    "vue": "^3.5.13",
    "vue-router": "^4.5.0"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^5.2.1",
    "electron": "^35.1.3",
    "vite": "^6.2.0",
    "vite-plugin-node-polyfills": "^0.23.0",
    "vite-plugin-optimizer": "^1.4.3"
  }
}

一定要重点关注入口:"main": "electron/main.cjs",和electron启动命令:"electron:serve": "vite build && electron ."

electron入口

在项目的根目录下新建文件夹/electron。

在文件夹中新建文件main.cjs

注意,一定要是.cjs,不是.js

js 复制代码
// 控制应用生命周期和创建原生浏览器窗口的模组
const { app, BrowserWindow, Menu } = require('electron')
const path = require('path')
require('@electron/remote/main').initialize()

function createWindow() {
  // 创建浏览器窗口
  const mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    frame: false, // 隐藏默认的标题栏
    webPreferences: {
      // 书写渲染进程中的配置
      nodeIntegration: true, //开启true这一步很重要,目的是为了vue文件中可以引入node和electron相关的API
      contextIsolation: false, // 可以使用require方法
    },
  })
  require('@electron/remote/main').enable(mainWindow.webContents)

  let env = 'pro'
  // 配置热更新
  if (env == 'pro') {
    const elePath = path.join(__dirname, '../node_modules/electron')
    require('electron-reload')('../', {
      electron: require(elePath),
    })
    // 热更新监听窗口
    mainWindow.loadURL('http://localhost:8888')
    // 打开开发工具
    mainWindow.webContents.openDevTools()
  } else {
    // 生产环境中要加载文件,打包的版本
    // Menu.setApplicationMenu(null)
    // 加载 index.html
    mainWindow.loadFile(path.resolve(__dirname, '../dist/index.html')) // 新增
  }
}
// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
  // 关闭默认菜单栏
  Menu.setApplicationMenu(null)
  createWindow()

  app.on('activate', function () {
    // 通常在 macOS 上,当点击 dock 中的应用程序图标时,如果没有其他
    // 打开的窗口,那么程序会重新创建一个窗口。
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// 除了 macOS 外,当所有窗口都被关闭的时候退出程序。 因此,通常对程序和它们在
// 任务栏上的图标来说,应当保持活跃状态,直到用户使用 Cmd + Q 退出。
app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})

启动

打开两个终端窗口,需要都在该项目的根目录。

先运行npm run dev

再运行npm run electron:serve

这样,electron就能根据vue的内容实时渲染

重写关闭、隐藏、最大化最小化

在vue的根组件App.vue中:

html 复制代码
<script setup>
import {
  Close,
  FullScreen,
  ArrowDown
} from '@element-plus/icons-vue'
import { getCurrentWindow } from '@electron/remote'
// 关闭
const closeApp = () => {
  const currentWindow = getCurrentWindow()
  currentWindow.close()
}
// 全屏/退出全屏应用
const fullScreenApp = () => {
  const currentWindow = getCurrentWindow()
  if (currentWindow.isFullScreen()) {
    currentWindow.setFullScreen(false)
  } else {
    currentWindow.setFullScreen(true)
  }
}

// 最小化应用
const hideApp = () => {
  const currentWindow = getCurrentWindow()
  currentWindow.minimize()
}
</script>

<template>
  <div>
    <div style="padding: 10pt; text-align: right;">
      <el-button type="warning" size="small" circle :icon="ArrowDown" @click="hideApp"></el-button>
      <el-button type="success" size="small" :icon="FullScreen" circle @click="fullScreenApp" />
      <el-button type="danger" size="small" :icon="Close" circle @click="closeApp" />
    </div>
    <router-view></router-view>
  </div>
</template>

<style scoped>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  color: #2c3e50;
}
</style>

先到这里,后面有什么好玩的继续更新

相关推荐
卸任9 小时前
Vibe coding工具使用心得
前端·ai编程
brien99 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance10 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M10 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写10 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李10 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易10 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
清晨Coding10 小时前
删了 Cookie 还能自动登录?Google系网站登录态自动恢复的原理分析
javascript
风骏时光牛马10 小时前
前沿视界
前端
kyriewen10 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员