惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

SecWiki News
SecWiki News
I
InfoQ
The Cloudflare Blog
人人都是产品经理
人人都是产品经理
博客园 - Franky
T
Tailwind CSS Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
量子位
博客园_首页
罗磊的独立博客
V
V2EX
李成银的技术随笔
大猫的无限游戏
大猫的无限游戏
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
True Tiger Recordings
Vercel News
Vercel News
Cyberwarzone
Cyberwarzone
Cisco Talos Blog
Cisco Talos Blog
F
Fox-IT International blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
M
Microsoft Research Blog - Microsoft Research
Know Your Adversary
Know Your Adversary
爱范儿
爱范儿
The Register - Security
The Register - Security
G
Google Developers Blog
The Hacker News
The Hacker News
Malwarebytes
Malwarebytes
S
Securelist
博客园 - 三生石上(FineUI控件)
Jina AI
Jina AI
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
S
SegmentFault 最新的问题
博客园 - 叶小钗
F
Fortinet All Blogs
Apple Machine Learning Research
Apple Machine Learning Research
宝玉的分享
宝玉的分享
博客园 - 聂微东
T
Threatpost
博客园 - 【当耐特】
D
Docker
P
Privacy & Cybersecurity Law Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
G
GRAHAM CLULEY
V
Visual Studio Blog
C
Cisco Blogs
IT之家
IT之家
S
Security Archives - TechRepublic
Latest news
Latest news
阮一峰的网络日志
阮一峰的网络日志

Mox的笔记库

细嗦下MLIR的环境搭建 | Mox的笔记库 博客重构:从Hexo到Astro | Mox的笔记库 2026PPoPP MLIR Tutorial学习 | Mox的笔记库 MacOS配置《明日方舟:终末地》 | Mox的笔记库 2025:向内生长 | Mox的笔记库 由mlir::ExecutionEngine引发的跨系统问题 | Mox的笔记库 WSL2配置Cuda-Tile环境记录(未完待续) | Mox的笔记库 Vibe Coding手搓项目记录 | Mox的笔记库 给Debian上包——以DuckDB为例 | Mox的笔记库 UCPD.sys事件存档 | Mox的笔记库 换新电脑之Mac mini M4从购买到配置 | Mox的笔记库 Mac配置MLX-C开发环境 | Mox的笔记库 RISC-V meets RDBMS——RISC-V架构上可运行数据库一览 | Mox的笔记库 DuckDB Sort实现调查 | Mox的笔记库 修复Redis在树莓派5上无法运行的问题 | Mox的笔记库 如何在MLIR中自定义类型并且输出运行 | Mox的笔记库 网站网络结构变更记录 | Mox的笔记库 EDBT25论文阅读:PhoebeDB——A Disk-Based RDBMS Kernel for High-Performance and Cost-Effective OLTP SIGMOD25论文阅读:BPF-DB:——A Kernel-Embedded Transactional Database Management System For eBPF Applications SIGMOD24文章阅读:Query Compilation Without Regrets | Mox的笔记库 论文阅读:Designing an Open Framework for Query Optimization and Compilation Apache Arrow Gandiva项目解析 | Mox的笔记库 VLDB24论文阅读:Cloud-Native Database Systems and Unikernels——Reimagining OS Abstractions for Modern Hardware NoisePage源码分析(未完待续) | Mox的笔记库 VLDB20论文阅读:Mainlining Databases——Supporting Fast Transactional Workloads on Universal Columnar Data File Formats VLDB17论文阅读:Relaxed Operator Fusion for In-Memory Databases:Making Compilation, Vectorization, and Prefetching Work Together At Last 论文阅读:How not to structure your database-backed web applications——a study of performance bugs in the wild SIGMOD24阅读:ROME——Robust Query Optimization via Parallel Multi-Plan Execution 文章阅读:First Past the Post-Evaluating Query Optimization in MongoDB SIGMOD文章阅读:Apache Calcite——A Foundational Framework for Optimized Query Processing Over Heterogeneous Data Sources VLDB23论文阅读:Analyzing the Impact of Cardinality Estimation on Execution Plans in Microsoft SQL Server SIGMOD22论文阅读:Efficient Massively Parallel Join Optimization for Large Queries VLDB论文阅读:Weaving Relations for Cache Performance VLDB22论文阅读:ConnectorX——Accelerating Data Loading From Databases to Dataframes 论文阅读:UniKraft-Fast, Specialized Unikernels the Easy Way 当DuckDB遇上RISC-V | Mox的笔记库 SIGMOD25论文阅读:An Elephant Under The Microscope——Analyzing The Interaction Of Optimizer Components In PostgreSQL 论文阅读:Compile-Time Analysis of Compiler Frameworks for Query Compilation VLDB23阅读:Bringing Compiling Databases to RISC Architectures LingoDB源码编译与分析 | Mox的笔记库 淦!MLIR输出Hello World不应该这么难! | Mox的笔记库 如何愉快的运行一个MLIR程序 | Mox的笔记库 2024:拥挤年代的想象与创造 | Mox的笔记库 如何给自己的博客添加MLIR和LLVM IR语法高亮 | Mox的笔记库 VLDB19-Parsing Gigabytes of JSON per Second论文阅读 CIDR25:Runtime-Extensible Parsers阅读 | Mox的笔记库 MLIR学习资料整理 | Mox的笔记库 SIGMOD24文章阅读:VeriTxn | Mox的笔记库 VLDB23文章阅读——Exploiting Cloud Object Storage for High-Performance Analytics VLDB24——OLAP on Modern Chiplet-Based Processors走马观花阅读 VLDB22:YeSQL文章阅读(已废弃) | Mox的笔记库 如何让数据库中的Python跑的更快-VLDB22-YeSQL文章阅读 | Mox的笔记库 你好,世界! | Mox的笔记库 让系统研究更有意义:HarmonyOS NEXT的教训和经验——讲座回顾 | Mox的笔记库 UNSW 24T3 COMP9336上课记录 | Mox的笔记库 Velox开发环境配置踩坑记录 | Mox的笔记库 MLIR Toy Tutorial实践记录 | Mox的笔记库 论文阅读:Declarative Sub-Operators for Universal Data Processing LLVM-Kaleidoscope实操踩坑记录 | Mox的笔记库 2024年7月RSSHub开发体验 | Mox的笔记库 澳洲大学计算机硕士比较 | Mox的笔记库 论文阅读——CDUL:CLIP-Driven Unsupervised Learning for Multi-Label Image Classification 论批量快速添加图片与视频水印的事 | Mox的笔记库 CVPR2023-CLIP算法调研 | Mox的笔记库 基于元信息写入的服务器压力测试 | Mox的笔记库 MjAyMw==,希望,前进与平庸之道 | Mox的笔记库 家庭组网IPv6+Mesh折腾 | Mox的笔记库 code-server初体验 | Mox的笔记库 从Nginx到Caddy | Mox的笔记库 Hexo部署安装全流程回顾 | Mox的笔记库 RMM观察与初探 | Mox的笔记库 计算机网络课设——UDP/TCP/TLS Socket实验 | Mox的笔记库 JQuery的XSS初探 | Mox的笔记库 生产实习记录 | Mox的笔记库 Fedora-CoreOS配置与试用(2023年) | Mox的笔记库 ServerSentEvent学习 | Mox的笔记库 报告翻译:容器云的安全挑战 | Mox的笔记库 Arch Linux迁移计划 | Mox的笔记库 Vagrant配置Metarget靶场环境 | Mox的笔记库 OpenAI-whisper折腾 | Mox的笔记库 202202,困惑,混乱与未曾设想之路 | Mox的笔记库 2022年Hack the box:Tier1免费区全解 | Mox的笔记库 Navidrome部署记录 | Mox的笔记库 长安杯2021-snake复现 | Mox的笔记库 报告概要翻译:OBFUSCATING C++ PROGRAMS VIA CONTROL FLOW FLATTENING 从零开始的Django CVE-2022-28346复现 | Mox的笔记库 2022CISCN(西北区赛)-The shinning | Mox的笔记库 Docker+QEMU+Arm64(Ubuntu)+环境配置(2022版) | Mox的笔记库 Arch Linux运行树莓派系统(2022年) | Mox的笔记库 2022CISCN初赛-ez_usb-复盘WriteUp | Mox的笔记库 NodeMCU-MicroPython配置实录 | Mox的笔记库 Django事务使用 | Mox的笔记库 记录第一次EduSRC上报 | Mox的笔记库 Jetbrain问题应急处理 | Mox的笔记库 Celery5.2学习&配置 | Mox的笔记库 Waline部署记录 | Mox的笔记库 2021年12月 Vivo千镜杯回顾 | Mox的笔记库 Frida hook初次实战 | Mox的笔记库 Log4j2漏洞复现 | Mox的笔记库 Windows的WSL2+Docker初探 | Mox的笔记库
Electron学习笔记 | Mox的笔记库
2023-08-27 · via Mox的笔记库

前言

这段时间在整理今年的资料。这篇文章记录于2023年初,当时的情况是要将网页端的内容移动到服务端,最省事省力的方案自然是用Electron解决(至于臃肿的问题,那就交给消费者自己去烦恼吧😂)

以下部分仅作记录,今天暂且就水一篇

安装

修改.yarnrc

registry "https://registry.npmmirror.com"

ELECTRON_MIRROR "https://npmmirror.com/mirrors/electron/"

ELECTRON_BUILDER_BINARIES_MIRROR "https://npmmirror.com/mirrors/electron-builder-binaries/"

Vue启动

npm create electron-vite

or

git clone https://github.com/electron-vite/electron-vite-vue

然后yarn

Quick start

mkdir my-electron-app && cd my-electron-app

yarn init

yarn add --dev electron

解决CSP问题

<!-- https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP -->

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">

预加载

你不能直接在主进程中编辑DOM,因为它无法访问渲染器 文档 上下文。 它们存在于完全不同的进程!

这是将 预加载 脚本连接到渲染器时派上用场的地方。 预加载脚本在渲染器进程加载之前加载,并有权访问两个 渲染器全局 (例如 windowdocument) 和 Node.js 环境。

创建一个名为 preload.js 的新脚本如下:

window.addEventListener('DOMContentLoaded', () => {

const replaceText = (selector, text) => {

const element = document.getElementById(selector)

if (element) element.innerText = text

}

for (const dependency of ['chrome', 'node', 'electron']) {

replaceText(`${dependency}-version`, process.versions[dependency])

}

})

要将此脚本附加到渲染器流程,请在你现有的 BrowserWindow 构造器中将路径中的预加载脚本传入 webPreferences.preload 选项。

// 需在当前文件内开头引入 Node.js 的 'path' 模块

const path = require('path')

// modify your existing createWindow() function

const createWindow = () => {

const win = new BrowserWindow({

width: 800,

height: 600,

webPreferences: {

preload: path.join(__dirname, 'preload.js')

}

})

win.loadFile('index.html')

}

// ...

进程通信

https://www.electronjs.org/zh/docs/latest/tutorial/ipc

主进程的主要目的是使用 BrowserWindow 模块创建和管理应用程序窗口

electron中的ipc通信(二)

大概是全网最详细的Electron ipc 讲解(一)——主进程与渲染进程的两情相悦

主进程与渲染进程通信

主进程

  • 一个electron只能有一个主进程
  • 主进程指的是,你在执行 electron . 命令后,对应的当前目录下面的package.json文件下面的main的指定文件将会被执行,这里指的是

渲染进程(Renderer Process)

  • 由主进程调用GUI接口创建的页面,都有自己的进程,叫做渲染进程。主进程通过实例化BrowserWindow,每个BrowserWindow实例都会渲染一个web页面,相互独立,当一个BrowserWindow被销毁,相应的渲染进程也会被终止。
  • 渲染进程被主进程管理,每个渲染进程相互独立,只管理他们自己的web页面

两者需要通信,就需要用ipc通信

Example

单向

主进程.ts(可以写NodeJS代码,访问本地存储)

ipcMain.on("async-message", (event, arg) => {

//异步消息回复

console.log(`async-message:我接收到了异步消息`, arg);

event.reply("async-reply", "哥们我收到消息了-来自异步");

});

ipcMain.on("sync-message", (event, arg) => {

//同步消息回复

console.log(`async-message:我接收到了同步消息`, arg);

event.returnValue = "哥们我收到消息了-来自同步";

});

渲染进程.ts

const { ipcRenderer } = require('electron');

ipcRenderer.on("async-reply", (event, arg) => {

console.log("异步消息:", arg);

data = JSON.parse(arg)

console.log(data);

});

ipcRenderer.send("async-message", "发个异步消息");

ipcRenderer.send进行触发,ipcRenderer.on对返回进行相应

双向

ipcRenderer.invokeipcMain.handle 搭配使用

const { ipcRenderer } = require('electron');

async function invokeMessageToMain() {

const replyMessage = await ipcRenderer.invoke('render-invoke-to-main', '我是渲染进程通过 invoke 发送的消息');

console.log('replyMessage', replyMessage);

}

ipcMain.handle('render-invoke-to-main', async (event, message) => {

console.log(`receive message from render: ${message}`)

const result = await asyncWork();

return result;

})

const asyncWork = async () => {

return new Promise(resolve => {

setTimeout(() => {

resolve('延迟 2 秒获取到主进程的返回结果')

}, 2000)

})

}

功能

读取文件

使用icp

Electron教程(五)读取本地文件内容, icpMain icpRenderer 之间的交互

双向

ipcMain.handle('render-invoke-to-main', async (event, message) => {

console.log(`receive message from render: ${message}`)

const result = await asyncWork();

return result;

})

async function asyncWork(){

return new Promise(resolve => {

let fs = require("fs");

fs.readFile('E:\\code\\test_node\\a.json', function (err, data) {

if (err) {

console.log(err)

resolve(err)

}

resolve(data.toString())

});

})

}

const replyMessage = await ipcRenderer.invoke('render-invoke-to-main', 'render invoke');

data = JSON.parse(replyMessage)

单向

ipcMain.on('asynchronous-message', function(event, arg) {

let fs = require("fs");

fs.readFile("E:\\code\\test_node\\a.json","utf8",(err,data)=>{

if(err){

event.sender.send('asynchronous-reply', "读取失败");

}else{

event.sender.send('asynchronous-reply', data);

}

})

});

const { ipcRenderer } = require('electron');

ipcRenderer.on("asynchronous-reply", function(event, arg) {

// 这里的arg是从主线程请求的数据

console.log(arg)

data = JSON.parse(arg)

console.log(data);

});

ipcRenderer.send("asynchronous-message", "ping");

使用预加载

修改DOM树

window.addEventListener('DOMContentLoaded', () => {

let readAndDisplay = () => {

let fs = require("fs");

fs.readFile("E:\\code\\test_node\\input.txt","utf8",(err, data) => {

if (err) return console.error(err);

console.log(data.toString());

});

}

document.querySelector('#btn1').addEventListener("click", event => {

readAndDisplay();

})

})

全屏

mainWindow = new BrowserWindow({

//...

fullscreenable:true,

fullscreen: true,

simpleFullscreen:true,

});

取消菜单栏

import { Menu } from 'electron'

Menu.setApplicationMenu(null) // null值取消顶部菜单栏

使用系统摄像头

未解决的issue

Electron加载HTTP页面打开本地摄像头

纯HTML5打开

Electron 从入门到实践07之实战 相机应用(还是mediaDevices.getUserMedia,但是保存到了本地)

Esc退出全屏

https://www.electronjs.org/zh/docs/latest/api/global-shortcut

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

在CreateWindow()中添加相关

globalShortcut.register('ESC', function () {

win.close()

})

流程模型

https://www.electronjs.org/zh/docs/latest/tutorial/process-model

Electron 应用程序的结构非常相似。 作为应用开发者,你将控制两种类型的进程:主进程渲染器进程。 这类似于上文所述的 Chrome 的浏览器和渲染器进程。

窗口管理

主进程的主要目的是使用 BrowserWindow 模块创建和管理应用程序窗口。

BrowserWindow 类的每个实例创建一个应用程序窗口,且在单独的渲染器进程中加载一个网页。 您可从主进程用 window 的 webContent 对象与网页内容进行交互。

const { BrowserWindow } = require('electron')

const win = new BrowserWindow({ width: 800, height: 1500 })

win.loadURL('https://github.com')

const contents = win.webContents

console.log(contents)

预加载(Preload 脚本)

预加载(preload)脚本包含了那些执行于渲染器进程中,且先于网页内容开始加载的代码 。 这些脚本虽运行于渲染器的环境中,却因能访问 Node.js API 而拥有了更多的权限。

预加载脚本可以在 BrowserWindow 构造方法中的 webPreferences 选项里被附加到主进程。

main.js

const { BrowserWindow } = require('electron')

//...

const win = new BrowserWindow({

webPreferences: {

preload: 'path/to/preload.js',

},

})

//...

因为预加载脚本与浏览器共享同一个全局 Window 接口,并且可以访问 Node.js API,所以它通过在全局 window 中暴露任意 API 来增强渲染器,以便你的网页内容使用。

进程间通信

https://www.electronjs.org/zh/docs/latest/tutorial/ipc

打包

electron-forge

https://www.electronforge.io/

electron-builder

资料

官方

https://www.electronjs.org/zh/docs/latest/

https://www.electronjs.org/

electron/electron-quick-start

blogs

electron 应用开发优秀实践

Bugs

Electron+Vite+Vue3中

public中可能会有几张无法打包

在App.vue中引用,会无法显示

应急解决方案:将public的打进入assets

After build, assets can not resolved correct. / 打包后,assets下资源路径不正确 #287