性能和安全
1786字约6分钟
2024-12-09
清单:性能建议
如果你尝试这些步骤,你的应用可能会略微简洁、快速,而且一般来说会更少出现资源不足的情况。
- 谨慎地加载模块
- 过早的加载和执行代码
- 不阻塞主进程
- 不阻塞渲染进程
- 不必要的polyfills
- 不必要的或者阻塞的网络请求
- 打包你的代码
- 当你不需要默认菜单时调用
Menu.setApplicationMenu(null)
1. 谨慎地加载模块
在向你的应用程序添加一个 Node.js 模块之前,请检查这个模块。 这个模块包含了多少依赖? 简单的一个 a require()
声明中包含了什么种类的资源? 你可能发现 NPM 包注册的最多的或者 Github 上Star 最多的模块实际上并不是最简单或者最小可用的模块。
当考虑一个模块时,我们建议你做以下检查:
- 包含的依赖项的大小
- 需要加载的
require()
资源 - 你所加载的资源能够执行你关心的操作
可以使用命令行上的单个命令生成用于加载模块的 CPU 配置文件和堆内存配置文件 在下面的示例中,我们看一下受欢迎的模块 request
。
node --cpu-prof --heap-prof -e "require('request')"
执行此命令将在您执行的目录下生成一个 .cpuprofile
和一个 .heapprofile
文件。 这两个文件都可以使用 Chrome
开发者工具进行分析,分别使用 Performance
和 Memory
标签 进行分析。
2. 过早的加载和执行代码
如果你有非常繁重的初始化操作,请考虑推迟进行。 程序启动立刻查看应用执行的全部工作。 考虑按照用户操作的顺序将它们错开执行,而不是立刻执行所有的操作。
在传统的 Node.js 开发中,我们常将所有 require()
语句置于代码顶部。若你在编写 Electron 应用程序时使用了无需立即加载的大型模块,且采用了相同写法,请将其推迟到更合适的时机加载。
3. 不阻塞主进程
Electron的主要进程(有时称为“浏览器进程”) 非常特殊:它是与你应用的所有其他进程的父进程,也是和操作系统交互的关键进程。 它负责处理窗口、交互以及应用程序内各个组件之间的通信。 它还包含了UI线程。
在任何情况下你都不应阻塞此进程或者运行时间长的用户界面线程。 阻塞UI线程意味着您的整个应用程序将冻结直到主进程准备好继续处理。
Electron强大的多进程架构随时准备帮助你完成你的长期任务,但其中也包含少量性能陷阱。
对于需要长期占用
CPU
的繁重任务,利用worker threads
,请考虑将它们移动到BrowserWindow
,或(作为最后手段)生成一个专用进程。尽可能避免使用同步
IPC
和@electron/remote
模块。 虽然有合法的使用案例,但很容易不知情地阻塞UI
线程。避免在主进程中使用阻塞
I/O
操作。 简而言之,每当 Node.js 的核心模块 (如fs
或child_process
) 提供一个同步版本或 异步版本,你更应该使用异步和非阻塞式的变量。
4. 不阻塞渲染进程
自从 Electron 使用了当前版本的 Chrome,你可以使用 Web 平台提供的最新和最优秀的功能来推迟或卸载繁重的操作,以使你的应用保持流畅和迅速的反应。
一般来说,所有用于构建现代浏览器的性能网络应用程序的建议,对于Electron 的渲染器也同样适用。 现在处理你的应用的主要两个方法是对于小的操作使用 requestIdleCallback()
而长时间运行的操作使用 Web Workers
。
requestIdleCallback()
: 允许开发者将函数排队为在进程进入空闲期后立刻执行。 它使你能够在不影响用户体验的情况下执行低优先级或后台执行的工作。
Web Workers
: Web Worker 为 Web 内容在后台线程中运行脚本提供了一种简单的方法。线程可以执行任务而不干扰用户界面。
5. 不必要的 polyfills
Electron的一大好处是,你准确地知道哪个引擎将解析你的 JavaScript, HTML 和 CSS。 如果你重新设计的代码是为整个网页编写的,请确保不会 polyfill 包含在 Electron 中的特性。
6. 不必要的或者阻塞的网络请求
避免从互联网中获取几乎不变化的资源,如果它可以轻松地与你的应用程序捆绑起来。
7. 打包你的代码
正如中已经指出的那样,"加载和运行代码太早", 调用 require() 是一项繁重的操作。 如果你能够这样做,将你的应用程序的代码打包到单个文件中。可使用打包工具来完成这个任务。
8. 当你不需要默认菜单时调用 Menu.setApplicationMenu(null)
Electron 在启动时将设置一个默认菜单,其中包含一些标准条目。 但是你的应用程序或许希望更改默认菜单,这么做有助于提高启动性能。
安全
- 有关如何正确上报 Electron 漏洞的信息,参阅 SECURITY.md.
- 对于上游 Chromium 漏洞: Electron 用其他版本的 Chromium 来更新。参阅 Electron Release Timelines
一般准则
- 使用最新版的 Electron 框架搭建你的程序
- 使用安全的 NPM 依赖
- 注意代码安全规范
- 隔离不受信任的内容
注意
无论如何,在启用 Node.js 集成的情况下,你都不该加载并执行远程代码。 相反,只使用本地文件(和您的应用打包在一起)来执行 Node.js 代码, 如果要显示远程内容,请使用 <webview>
或WebContentsView
,并确保禁用 nodeIntegration
,以及启用 contextIsolation
。
清单:安全建议
- 只加载安全的内容
- 禁止在所有渲染器中使用Node.js集成显示远程内容
- 在所有渲染器中启用上下文隔离
- 启用进程沙盒化
- 在所有加载远程内容的会话中使用
ses.setPermissionRequestHandler()
. - 不要禁用
webSecurity
- 定义一个
Content-Security-Policy
并设置限制规则(如:script-src 'self'
) - 不要设置
allowRunningInsecureContent
为true
- 不要开启实验性功能
- 不要使用
enableBlinkFeatures
<webview>
:不要使用allowpopups
<webview>
:验证选项与参数- 禁用或限制网页跳转
- 禁用或限制新窗口创建
- 不要对不可信的内容使用
shell.openExternal
- 使用当前版本的
Electron
- 验证所有
IPC
消息的sender
- 不要使用
file://
,而是使用通用协议 - 检查你可以更换的
Fuses