首页
/ Electron WebPreferences 深度指南:选项语义、默认值与渲染进程配置的 C++ 实现

Electron WebPreferences 深度指南:选项语义、默认值与渲染进程配置的 C++ 实现

2026-09-06 17:29:32作者:江焘钦

本文以 Electron 官方 WebPreferences 结构文档为主体,完整解析 webPreferences 中每一项可选配置的含义与默认值,并结合 Electron 仓库中 web_contents_preferences.ccelectron_api_web_contents.ccoptions_switches.h 的源码,说明这些选项如何被解析为渲染进程命令行开关与 Blink 偏好,帮助你在创建窗口时做出安全且可验证的配置决策。

WebPreferences 是什么,在哪里生效

WebPreferences 是创建 BrowserWindowWebContentsViewwebContents 以及 <webview> 时用于描述"这个页面以什么规则运行"的配置对象。典型用法如下:

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

const win = new BrowserWindow({
  width: 800,
  height: 600,
  webPreferences: {
    preload: require('node:path').join(__dirname, 'preload.js'),
    contextIsolation: true,
    nodeIntegration: false,
    sandbox: true
  }
});

从源码结构看,WebPreferences 的处理分成两层:

  1. WebContents 初始化层electron_api_web_contents.cc 在构造阶段从 options 字典中逐项读取 devToolsoffscreensession/partitiondisableWakeLocks 等字段。例如 devTools 选项在此被解析:

    // Whether to enable DevTools.
    options.Get("devTools", &enable_devtools_);
    

    (见 electron_api_web_contents.cc#L933-L934

  2. WebContentsPreferences 持久层web_contents_preferences.cc 中的 WebContentsPreferences 作为 WebContentsUserData 挂载,在 SetFromDictionary 中把字典逐项映射为成员变量,并在 OverrideWebkitPrefs 中把它们写回 Blink 的 web_pref::WebPreferences,真正影响页面渲染行为。

所有选项的名称常量集中在 options_switches.h(如 kNodeIntegration = "nodeIntegration"kContextIsolation = "contextIsolation"kPreloadScript = "preload"),可以以此核对文档字段与底层解析是否一一对应。

值得注意的一点:SetFromDictionary 结尾会调用 SaveLastPreferences(),把初始配置的一份快照存入 last_web_preferences_。因此运行时可以通过 webContents.getLastWebPreferences() 回查该 WebContents 最初使用的关键偏好(解析出的实现见 electron_api_web_contents.cc#L5064),这在排查"这个页面到底以什么沙箱/隔离策略运行"时非常实用。

进程模型与安全类选项

这组选项决定渲染进程里有哪些能力可用,是 webPreferences 中最核心的部分。

nodeIntegration / nodeIntegrationInWorker / nodeIntegrationInSubFrames

  • nodeIntegration (boolean, 默认 false) — 是否在页面中启用 Node 集成。
  • nodeIntegrationInWorker (boolean, 默认 false) — 是否在 Web Worker 中启用 Node 集成,更多说明见 多线程教程
  • nodeIntegrationInSubFrames (boolean, 实验性) — 在 iframe 等子框架中启用 Node 支持。开启后你的 preload 脚本会在每个 iframe 中加载,可用 process.isMainFrame 判断当前是否处于主框架。

sandbox:默认开启,且与 Node 集成互斥

sandbox (boolean) — 设置后会沙箱化该窗口关联的渲染进程,使其兼容 Chromium 的操作系统级沙箱并禁用 Node.js 引擎。它与 nodeIntegration 不是同一回事:沙箱模式下 preload 脚本可用的 API 更为有限(详见 沙箱教程)。自 Electron 20 起默认值为 true,且当 nodeIntegration 设为 true 时沙箱会自动关闭。

这一"自动关闭"行为在源码中可以直接看到。web_contents_preferences.cc#L87-L99RendererProcessPreferences::From 实现如下:

bool sandbox;
if (web_preferences.Get(options::kSandbox, &sandbox)) {
  prefs.sandboxed = sandbox;
} else {
  bool node_integration = false, node_integration_in_worker = false;
  web_preferences.Get(options::kNodeIntegration, &node_integration);
  web_preferences.Get(options::kNodeIntegrationInWorker, &node_integration_in_worker);
  prefs.sandboxed = !(node_integration || node_integration_in_worker);
}

也就是说:显式传了 sandbox 时以传参为准;没传时,只要 nodeIntegrationnodeIntegrationInWorker 任一为 true,渲染进程就不会被沙箱化。随后 AppendCommandLineSwitchesweb_contents_preferences.cc#L126-L159)把它翻译为实际的进程命令行:

if (sandboxed || can_sandbox_frame) {
  command_line->AppendSwitch(switches::kEnableSandbox);   // --enable-sandbox
} else if (!command_line->HasSwitch(switches::kEnableSandbox)) {
  command_line->AppendSwitch(sandbox::policy::switches::kNoSandbox);  // --no-sandbox
  command_line->AppendSwitch(::switches::kNoZygote);                  // --no-zygote
}

另外 CanUseSpareRendererweb_contents_preferences.cc#L161-L171)表明:只有沙箱开启、非离屏、无 experimentalFeatures、无 scrollBounce(macOS)、无 additionalArguments、无自定义 Blink 特性时,该 WebContents 才允许复用预热的备用渲染进程——这也解释了为什么大量自定义 webPreferences 会改变进程分配行为。

preload:始终拥有 Node 访问权(沙箱下受限)

preload (string) — 指定在页面其他脚本运行之前加载的脚本。无论 nodeIntegration 开关如何,该脚本都会运行;取值必须是脚本的绝对文件路径。当 node 集成关闭时,preload 脚本可以把 Node 全局符号重新引入全局作用域,示例见 context-bridge 文档

源码中对该路径有强制校验(web_contents_preferences.cc#L296-L304):

base::FilePath::StringType preload_path;
if (web_preferences.Get(options::kPreloadScript, &preload_path)) {
  base::FilePath preload(preload_path);
  if (preload.IsAbsolute()) {
    preload_path_ = preload;
  } else {
    LOG(ERROR) << "preload script must have absolute path.";
  }
}

相对路径会被记为错误日志且不会生效,这正是文档强调"绝对路径"的原因。

contextIsolation:Electron API 与页面的隔离

contextIsolation (boolean, 默认 true) — 是否将 Electron API 和 preload 脚本运行在独立的 JavaScript 上下文中。开启后,preload 脚本所在上下文只能访问自己专属的 documentwindow 全局变量以及自己的 JavaScript 内建对象(ArrayObjectJSON 等),这些对页面内容完全不可见;Electron API 也只存在于 preload 中,页面加载的内容无法篡改 preload 与 Electron API。加载不可信远程内容时应开启此选项,其技术与 Chrome Content Scripts 的隔离机制相同。在 DevTools 中可通过 Console 标签页顶部的下拉框选择 "Electron Isolated Context" 进入该上下文调试。

映射到 Blink 的位置在 OverrideWebkitPrefs 中:prefs->context_isolation = context_isolation_;web_contents_preferences.cc#L485)。

webviewTag 及其安全注意

webviewTag (boolean, 默认 false) — 是否启用 <webview> 标签(见 webview 标签文档)。注意<webview> 上配置的 preload 脚本在执行时拥有 Node 集成,因此必须确保不可信内容无法创建一个带有恶意 preload<webview>。可以在 webContents 上监听 will-attach-webview 事件,剥离 preload 并对 <webview> 的初始设置做校验或修改。

additionalArguments

additionalArguments (string[]) — 追加到该应用渲染进程 process.argv 的字符串列表,适合向 preload 脚本传递少量数据。源码中它们通过 command_line->AppendArg(arg) 逐个拼入命令行(web_contents_preferences.cc#L149-L151)。

会话与分区:session / partition

  • session (Session, 可选) — 设置页面使用的会话。也可以改用 partition 字符串。两者同时提供时session 优先。默认为默认会话。
  • partition (string, 可选) — 按会话的分区字符串设置页面会话。以 persist: 开头时,应用内所有使用相同 partition 的页面共享一个持久会话;没有 persist: 前缀时使用内存会话。通过相同的 partition,多个页面可以共享同一会话。默认为默认会话。

解析优先级在 electron_api_web_contents.cc#L946-L956 中体现得很直白:

// Obtain the session.
std::string partition;
api::Session* session = nullptr;
if (options.Get("session", &session) && session) {
} else if (options.Get("partition", &partition)) {
  session = Session::FromPartition(isolate, partition);
} else {
  // Use the default session if not specified.
  session = Session::FromPartition(isolate, "");
}

即:session 对象 > partition 字符串 > 默认会话(空 partition)。

内容渲染与显示类选项

功能开关

选项 类型 默认值 说明
devTools boolean true 是否启用 DevTools。设为 false 后无法再调用 BrowserWindow.webContents.openDevTools() 打开 DevTools
javascript boolean true 启用 JavaScript 支持
images boolean true 启用图片支持
imageAnimationPolicy string animate 图片(如 GIF)动画策略:animate / animateOnce / noAnimation
textAreasAreResizable boolean true 使 <textarea> 元素可调整大小
webgl boolean true 启用 WebGL 支持(源码中同时控制 webgl1 与 webgl2 开关)
plugins boolean false 是否启用插件
experimentalFeatures boolean false 启用 Chromium 实验性 Web 平台特性(会追加 --enable-experimental-web-platform-features 开关)
scrollBounce boolean (macOS) false 启用 macOS 滚动回弹(橡皮筋)效果,非 macOS 构建中该分支被 BUILDFLAG(IS_MAC) 编译排除
enableBlinkFeatures string 逗号分隔的特性字符串列表,如 CSSVariables,KeyboardEventKey。完整特性列表见 Chromium 源码树中的 third_party/blink/renderer/platform/runtime_enabled_features.json5
disableBlinkFeatures string 同上,用于禁用特性。两者在 web_contents_preferences.cc#L153-L158 中分别转为 --enable-blink-features / --disable-blink-features 命令行参数
spellcheck boolean true 是否启用内置拼写检查
enableWebSQL boolean true 是否启用 WebSQL API

imageAnimationPolicy 的取值映射见 SetImageAnimationPolicyweb_contents_preferences.cc#L327-L342),三个字符串分别对应 Blink 的 ImageAnimationPolicy 三个枚举值。

字体与编码

  • defaultFontFamily (Object) — 按字体类别设置默认字体,每个键都有各自的缺省字体:

    • standard — 默认 Times New Roman
    • serif — 默认 Times New Roman
    • sansSerif — 默认 Arial
    • monospace — 默认 Courier New
    • cursive — 默认 Script
    • fantasy — 默认 Impact
    • math — 默认 Latin Modern Math

    源码中这些键分别写入 standard_font_family_mapserif_font_family_mapsans_serif_font_family_mapfixed_font_family_mapcursive_font_family_mapfantasy_font_family_mapmath_font_family_mapweb_contents_preferences.cc#L444-L473)。

  • defaultFontSize (Integer) — 默认 16

  • defaultMonospaceFontSize (Integer) — 默认 13

  • minimumFontSize (Integer) — 默认 0

  • defaultEncoding (string) — 默认 ISO-8859-1

安全策略:webSecurityallowRunningInsecureContent

  • webSecurity (boolean, 默认 true) — 设为 false 会禁用同源策略(通常用于测试站点),并且如果用户没有显式设置 allowRunningInsecureContent,会将其自动置为 true
  • allowRunningInsecureContent (boolean, 默认 false) — 允许 https 页面运行来自 http URL 的 JavaScript、CSS 或插件。

这个"自动连带"逻辑在 web_contents_preferences.cc#L262-L265 中:

if (!web_preferences.Get(options::kAllowRunningInsecureContent,
                         &allow_running_insecure_content_) &&
    !web_security_)
  allow_running_insecure_content_ = true;

V8 代码缓存相关:v8CacheOptions (string) — 强制 Blink 使用的 V8 代码缓存策略,可选值:

  • none — 禁用代码缓存
  • code — 基于启发式的代码缓存(默认策略)
  • bypassHeatCheck — 绕过缓存启发式判断但延迟编译
  • bypassHeatCheckAndEagerCompile — 同上但立即编译

字符串到枚举的映射在 gin 转换器中(web_contents_preferences.cc#L58-L73)。

交互、窗口行为与性能类选项

  • zoomFactor (number, 默认 1.0) — 页面默认缩放因子,3.0 表示 300%

  • zoomMode (string, 默认 'default') — 页面初始缩放模式,可用模式见 contents.setZoomMode

  • backgroundThrottling (boolean, 默认 true) — 页面进入后台时是否节流动画与定时器,同时影响 Page Visibility API。当单个 browserWindow 中至少一个 webContents 禁用了 backgroundThrottling 时,整个窗口及其包含的所有 webContents 的帧都会继续绘制与交换。

  • offscreen (Object | boolean, 默认 false) — 是否为浏览器窗口启用离屏渲染,详见离屏渲染教程offscreen 既可以传布尔值也可以传对象(解析逻辑见 electron_api_web_contents.cc#L904-L924):

    • useSharedTexture (boolean, 实验性, 默认 false) — 是否使用 GPU 共享纹理加速 paint 事件。
    • sharedTexturePixelFormat (string, 实验性, 默认 argb) — 请求的共享纹理输出格式,名称源自 Chromium media::VideoPixelFormat 枚举后缀,仅支持其中一部分;实际输出像素格式与色彩空间应以 paint 事件中的 OffscreenSharedTexture 对象为准:
      • argb — 8 位 unorm RGBA,SRGB SDR 色彩空间
      • rgbaf16 — 16 位浮点 RGBA,scRGB HDR 色彩空间
      • nv12 — 12bpp,Y 平面后跟 2x2 交错的 UV 平面,REC709 色彩空间
    • deviceScaleFactor (number, 实验性) — 离屏渲染输出的设备缩放因子,未设置时默认 1
  • enablePreferredSizeMode (boolean, 默认 false) — 启用首选尺寸模式。首选尺寸是容纳文档布局(无需滚动)所需的最小尺寸;开启后,首选尺寸变化时会在 WebContents 上触发 preferred-size-changed 事件。

  • transparent (boolean, 默认 true) — 是否为客制页面启用背景透明。注意:客制页面的文字与背景色派生自其根元素的 color scheme;启用透明后文字颜色仍会随主题变化,但背景保持透明。源码中该值直接映射为背景色(web_contents_preferences.cc#L284-L287):

    bool transparent;
    if (web_preferences.Get(options::kTransparent, &transparent) && transparent) {
      background_color_ = SK_ColorTRANSPARENT;
    }
    
  • autoplayPolicy (string, 默认 no-user-gesture-required) — 窗口内容的自动播放策略,可选 no-user-gesture-requireduser-gesture-requireddocument-user-activation-required(字符串到 Blink 枚举的映射见 web_contents_preferences.cc#L41-L56)。

  • disableHtmlFullscreenWindowResize (boolean, 默认 false) — 进入 HTML Fullscreen 时是否阻止窗口调整大小。

  • accessibleTitle (string) — 仅提供给屏幕阅读器等辅助工具的替代标题,对用户不可见。

  • navigateOnDragDrop (boolean, 默认 false) — 将文件或链接拖放到页面上时是否触发导航。

  • focusOnNavigation (boolean, 默认 true) — 导航时是否聚焦该 WebContents。

  • disableWakeLocks (boolean, 默认 false) — 是否禁用该 WebContents 的唤醒锁(wake lock)。

  • enableDeprecatedPaste (boolean, 已废弃, 默认 false) — 是否启用 pasteexecCommand

  • 对话框保护三件套:

    • safeDialogs (boolean, 默认 false) — 是否启用浏览器风格的连续对话框保护;
    • safeDialogsMessage (string) — 触发连续对话框保护时显示的消息,未定义时使用默认消息(当前默认为英文,未本地化);
    • disableDialogs (boolean, 默认 false) — 是否完全禁用对话框,会覆盖 safeDialogs

默认值速查表

选项 默认值 选项 默认值
devTools true experimentalFeatures false
nodeIntegration false scrollBounce (macOS) false
nodeIntegrationInWorker false webSecurity true
sandbox true(Electron 20+) allowRunningInsecureContent false
contextIsolation true images true
webviewTag false imageAnimationPolicy animate
javascript true textAreasAreResizable true
images true webgl true
plugins false webSecurity true
zoomFactor 1.0 zoomMode 'default'
offscreen false deviceScaleFactor(离屏对象内) 1
sharedTexturePixelFormat argb useSharedTexture false
defaultFontSize 16 defaultMonospaceFontSize 13
minimumFontSize 0 defaultEncoding ISO-8859-1
backgroundThrottling true enablePreferredSizeMode false
transparent true spellcheck true
enableWebSQL true v8CacheOptions code
autoplayPolicy no-user-gesture-required disableHtmlFullscreenWindowResize false
safeDialogs false disableDialogs false
navigateOnDragDrop false focusOnNavigation true
disableWakeLocks false enableDeprecatedPaste(已废弃) false

未在上表出现的选项(preloadsessionpartitionadditionalArgumentsenableBlinkFeaturesdisableBlinkFeaturesdefaultFontFamilyaccessibleTitlesafeDialogsMessagenodeIntegrationInSubFrames)本身没有布尔型默认值,行为以"未设置"或文档描述的缺省字体为准(如 standard 缺省 Times New RomansansSerif 缺省 Arialmonospace 缺省 Courier Newcursive 缺省 Scriptfantasy 缺省 Impactmath 缺省 Latin Modern Math)。

配置在运行时的可验证性:getLastWebPreferences

WebContentsPreferences 在每次写入配置后都会调用 SaveLastPreferences() 生成快照(web_contents_preferences.cc#L397-L420),保存的键包括:nodeIntegrationnodeIntegrationInWorkernodeIntegrationInSubFramessandboxcontextIsolationjavascriptwebviewTagdisablePopupswebSecurityallowRunningInsecureContentexperimentalFeaturesenableBlinkFeaturesdisableDialogssafeDialogssafeDialogsMessagedisableWakeLocks

这份快照通过 webContents.getLastWebPreferences() 暴露给 JavaScript,是验证"配置到底生效了没有"的最直接手段,例如:

app.whenReady().then(() => {
  const win = new BrowserWindow({ webPreferences: { nodeIntegration: true } });
  win.webContents.on('did-finish-load', () => {
    const prefs = win.webContents.getLastWebPreferences();
    console.log(prefs.sandbox);         // false:开启 nodeIntegration 后沙箱自动关闭
    console.log(prefs.contextIsolation); // true:上下文隔离不受影响
  });
});

结合上文的 RendererProcessPreferences 源码可以预知输出:nodeIntegration: true 会经由 sandboxed = !(node_integration || node_integration_in_worker) 推导出沙箱关闭,与 sandbox 文档描述的行为完全一致。

典型组合建议

基于文档与源码中可验证的行为,几组常见组合如下:

  1. 加载不可信远程内容(推荐默认)contextIsolation: true(默认)+ 关闭 nodeIntegration + sandbox: true + 用 preload 通过 context bridge 暴露最小 API。preload 必须写绝对路径,否则只会被记录错误日志而不加载。
  2. 需要 Node 能力的内部应用nodeIntegration: true。此时沙箱会自动关闭,getLastWebPreferences()sandboxfalse;同时注意该 WebContents 不再满足复用备用渲染进程的条件。
  3. 多页面共享登录态/缓存:为不同页面域设置不同 partition(需要持久化时加 persist: 前缀),或传入显式的 session 对象;两者同时提供时 session 胜出。
  4. 离屏渲染集成到自绘 UIoffscreen: { useSharedTexture, sharedTexturePixelFormat, deviceScaleFactor },配合教程 offscreen-rendering 使用;注意共享纹理相关字段均为实验性能力。

参考索引

登录后查看全文
热门项目推荐
相关项目推荐