Electron 重大更改

2023-02-16 17:17 更新

這里將記錄重大更改,并在可能的情況下向JS代碼添加棄用警告,在這更改之前至少會有一個重要版本.

重大更改的類型?

本文檔使用以下約定對重大更改進行分類:

  • API 更改:已更改的 API 會以某種方式使未更新的代碼必定拋出異常。
  • 行為改變:Electron 的行為已經(jīng)改變,但并不一定拋出相應的異常。
  • 默認值更改:依賴于默認值的代碼的行為可能被破壞,但不保證會拋出相應的異常。 您可以通過顯式指定該值的方式恢復舊的默認行為。
  • 已廢棄:該 API 已標記為廢棄。 該 API 依舊可正常運作,但會拋出已廢棄警告,并在將來會移除。
  • 已移除:該 API 或功能已移除,Electron團隊不再對此提供支持。

計劃重寫的 API (23.0)?

已刪除:BrowserWindow scroll-touch-* 事件

在 BrowserWindow 上已棄用的 scroll-touch-begin、scroll-touch-end 和 scroll-touch-edge 事件已被刪除。相反,使用 WebContents 上新提供的輸入事件事件。

// Removed in Electron 23.0
win.on('scroll-touch-begin', scrollTouchBegin)
win.on('scroll-touch-edge', scrollTouchEdge)
win.on('scroll-touch-end', scrollTouchEnd)

// Replace with
win.webContents.on('input-event', (_, event) => {
  if (event.type === 'gestureScrollBegin') {
    scrollTouchBegin()
  } else if (event.type === 'gestureScrollUpdate') {
    scrollTouchEdge()
  } else if (event.type === 'gestureScrollEnd') {
    scrollTouchEnd()
  }
})

計劃重寫的 API (22.0)?

已廢棄: WebContents new-window 事件

WebContents 中的 new-window 事件已經(jīng)被廢棄。 已棄用:webContents.setWindowOpenHandler()。

// Removed in Electron 21
webContents.on('new-window', (event) => {
  event.preventDefault()
})

// Replace with
webContents.setWindowOpenHandler((details) => {
  return { action: 'deny' }
})

已廢棄:Browserwindow scroll-touch-* 事件

在 BrowserWindow 上已棄用的 scroll-touch-begin、scroll-touch-end 和 scroll-touch-edge 事件已被刪除。 相反,使用新的 input-event WebContents 上的事件。

// Deprecated
win.on('scroll-touch-begin', scrollTouchBegin)
win.on('scroll-touch-edge', scrollTouchEdge)
win.on('scroll-touch-end', scrollTouchEnd)

// Replace with
win.webContents.on('input-event', (_, event) => {
  if (event.type === 'gestureScrollBegin') {
    scrollTouchBegin()
  } else if (event.type === 'gestureScrollUpdate') {
    scrollTouchEdge()
  } else if (event.type === 'gestureScrollEnd') {
    scrollTouchEnd()
  }
})

計劃重寫的 API (21.0)?

Behavior Changed: V8 Memory Cage enabled

V8 內(nèi)存籠已啟用,這對使用 ArrayBuffer 或 Buffer 包裝非 V8 內(nèi)存的本機模塊有影響。

API Changed: webContents.printToPDF()

webContents.printToPDF() 已修改為符合 Chrome DevTools 協(xié)議中的 Page.printToPDF。這是為了解決上游的變化而進行的更改,這些更改使我們以前的實施變得站不住腳并且充滿了錯誤。

參數(shù)更改

  • ?pageRanges?

參數(shù)移除

  • ?printSelectionOnly?
  • ?marginsType?
  • ?headerFooter?
  • ?scaleFactor?

參數(shù)添加

  • ?headerTemplate?
  • ?footerTemplate?
  • ?displayHeaderFooter?
  • ?margins?
  • ?scale?
  • ?preferCSSPageSize?
// Main process
const { webContents } = require('electron')

webContents.printToPDF({
  landscape: true,
  displayHeaderFooter: true,
  printBackground: true,
  scale: 2,
  pageSize: 'Ledger',
  margins: {
    top: 2,
    bottom: 2,
    left: 2,
    right: 2
  },
  pageRanges: '1-5, 8, 11-13',
  headerTemplate: '<h1>Title</h1>',
  footerTemplate: '<div><span class="pageNumber"></span></div>',
  preferCSSPageSize: true
}).then(data => {
  fs.writeFile(pdfPath, data, (error) => {
    if (error) throw error
    console.log(`Wrote PDF successfully to ${pdfPath}`)
  })
}).catch(error => {
  console.log(`Failed to write PDF to ${pdfPath}: `, error)
})

計劃重寫的 API (20.0)?

默認值被更改:默認情況下,渲染器不為 nodeIntegration: true 將進行沙盒處理

之前, 指定預加載腳本的渲染器默認不啟用沙盒。 這意味著默認情況下,預加載腳本可以訪問Node.js。 在 Electron 20中,此默認值將被更改。 從Electron 20開始,渲染器 默認情況下會被沙盒化,除非指定了 nodeIntegration: true 或 sandbox: false 。

如果預加載腳本不依賴于 Node,則無需執(zhí)行任何操作。 如果 preload 腳本依賴于 Node,請重構(gòu)代碼,或從渲染器中刪除 Node 用法 ,或者顯式指定相關(guān)渲染器 sandbox: false 。

已刪除:Linux 上的 skipTaskbar

在 X11上, skipTaskbar 向 X11 窗口管理器發(fā)送一條 _NET_WM_STATE_SKIP_TASKBAR 消息。 Wayland沒有與其一致的功能,并且已知的 變通辦法具有不可接受的理由(如,在GNOME中Window.is_skip_taskbar 需要不安全模式),因此Electron無法在Linux上支持此功能。

API Changed: session.setDevicePermissionHandler(handler)

當使用 session.setDevicePermissionHandler(handler) 時,調(diào)用的處理程序?qū)ζ鋮?shù)進行了更改。此處理程序不再傳遞框架 WebFrameMain,而是傳遞原點,這是檢查設(shè)備權(quán)限的原點。

計劃重寫的 API (19.0)?

已刪除:IA32 Linux 二進制文件?

這是由于Chromium 102.0.4999.0放棄了對IA32 Linux的支持。 因此,刪除了對IA32 Linux 的支持。

計劃重寫的 API (18.0)?

已移除: nativeWindowOpen

在 Electron 15之前, window.open 默認使用 BrowserWindowProxy。這意味著 window.open('about:blank') 無法打開可同步編寫腳本的子窗口,以及其他不兼容性。自 Electron 15 起, nativeWindowOpen 將默認啟用。

計劃重寫的 API (17.0)?

已移除:渲染器中的 desktopCapturer.getSources

desktopCapturer.getSources API 現(xiàn)在僅在主進程中可用。 為了提高Electron 應用程序在默認情況下的安全性,已對此做了修改。

如果需要此功能,可以按如下方式替換它:

// 主進程
const { ipcMain, desktopCapturer } = require('electron')

ipcMain.handle(
  'DESKTOP_CAPTURER_GET_SOURCES',
  (event, opts) => desktopCapturer.getSources(opts)
)
// 渲染器進程
const { ipcRenderer } = require('electron')

const desktopCapturer = {
  getSources: (opts) => ipcRenderer.invoke('DESKTOP_CAPTURER_GET_SOURCES', opts)
}

然而,您應該考慮進一步限制返回到 渲染器的信息; 例如向用戶顯示源選擇器并只 返回選定的源。

已廢棄:nativeWindowOpen

在 Electron 15之前, window.open 默認使用 BrowserWindowProxy。這意味著 window.open('about:blank') 無法打開可同步編寫腳本的子窗口,以及其他不兼容性。 自 Electron 15 起, nativeWindowOpen 將默認啟用。

計劃重寫的 API (16.0)?

Behavior Changed: crashReporter implementation switched to Crashpad on Linux

Linux上 crashReporter API的底層實現(xiàn)已經(jīng) 從Breakpad更改為Crashpad,使其與Windows和Mac保持一致。 因此 子進程現(xiàn)在自動被監(jiān)視, 且調(diào)用 process.crashReporter.start 在Node子進程中不再需要 (并且 不被建議,因為它將啟動Crashpad報告器的二次實例) 。

在 Linux 上報告注釋的方式也有一些細微的變化,包括長整型值將不再在附加 __1、 __2 等 附加的注釋之間拆分,而是將在 (新的、更長的) 注釋值限制處被截斷。

已棄用:在渲染器中的 desktopCapturer.getSources

渲染器中 desktopCapturer.getSources API 的使用已被棄用,并將被刪除。 此更改提高了 Electron 應用程序的默認安全性。

計劃重寫的 API (15.0)?

默認更改: nativeWindowOpen 默認為 true

在 Electron 15之前, window.open 默認使用 BrowserWindowProxy。這意味著 window.open('about:blank') 無法打開可同步編寫腳本的子窗口,以及其他不兼容性。 nativeWindowOpen 不再是實驗性的,現(xiàn)在是默認的。

計劃重寫的 API (14.0)?

Removed: remote module

remote 模塊在 Electron 12 廢棄,并將在 Electron 14 被移除. 由@electronic/remote 模塊替代。

// 在 Electron 12 廢除:
const { BrowserWindow } = require('electron').remote
// 替換為:
const { BrowserWindow } = require('@electron/remote')

// 在主進程中:
require('@electron/remote/main').initialize()

已移除: app.allowRendererProcessReuse

作為我們計劃的一部分, app.allowRendererProcessReuse屬性將被刪除,以 與Chromium在安全性,性能和可維護性方面的流程模型更緊密地保持一致。

有關(guān)更多詳細信息,請參閱 #18397.

Removed: Browser Window Affinity

構(gòu)建新的 BrowserWindow 對象時的 affinity 選項將會被刪除, 這一點將作為我們計劃的一部分,以更緊密地與Chromium的流程模型保持一致,以實現(xiàn)安全性,高性能和可維護性。

有關(guān)更多詳細信息,請參閱 #18397.

API 更改: window.open()

可選參數(shù) frameName 將不再設(shè)置窗口的標題。 該功能現(xiàn)在遵循 原生文檔 中的約束,由名為 windowName 的參數(shù)控制。

如果您正在使用此參數(shù)來設(shè)置窗口的標題,您可以使用 ?win.setTitle(title)?。

已移除: worldSafeExecuteJavaScript

在 Electron 14, worldSafeExecuteJavaScript 將被移除。 除此之外沒有其他方式,請保證您的代碼中包含該屬性。 Electron 12中默認啟用該屬性。

若您使用了 webFrame.executeJavaScript 或 webFrame.executeJavaScriptInIsolatedWorld,這個改動會對您造成影響。 您將需要確保這些方法中任何一種返回的值都被 Context Bridge API 支持,因為這些方法使用相同的值傳遞語意。

Removed: BrowserWindowConstructorOptions inheriting from parent windows?

在 Electron 14 之前,使用 window.open 打開的窗口將從其父窗口繼承 BrowserWindow 構(gòu)造函數(shù)選項,例如透明和可調(diào)整大小。從 Electron 14開始,此行為已被刪除, 窗口將不會繼承他們父窗口的任何 BrowserWindow constructor 選項。

相反,使用 setWindowOpenHandler 顯式設(shè)置新窗口的選項:

webContents.setWindowOpenHandler((details) => {
  return {
    action: 'allow',
    overrideBrowserWindowOptions: {
      // ...
    }
  }
})

已移除: additionalFeatures

WebContents 的 new-window 和 did-create-window 事件中已棄用的 additionalFeatures 屬性已被刪除。由于 new-window 使用位置參數(shù),參數(shù)仍然存在,但將始終是空數(shù)組 []。(但請注意, new-window 事件本身 已被棄用,取而代之的是 setWindowOpenHandler。)窗口功能中的裸鍵現(xiàn)在將在選項對象中顯示為值為 true 的鍵。

// Removed in Electron 14
// Triggered by window.open('...', '', 'my-key')
webContents.on('did-create-window', (window, details) => {
  if (details.additionalFeatures.includes('my-key')) {
    // ...
  }
})

// Replace with
webContents.on('did-create-window', (window, details) => {
  if (details.options['my-key']) {
    // ...
  }
})

計劃重寫的 API (13.0)?

API 更改: session.setPermissionCheckHandler(handler)

handler 方法的第一個參數(shù)曾是 webContents,但現(xiàn)在可以為 null。 為正確響應權(quán)限檢查,您需要使用requestingOrigin、embeddingOrigin 和 securityOrigin 這些屬性。 因為 webContents 現(xiàn)在可能為 null,您不應當依賴此參數(shù)。

// 舊代碼
session.setPermissionCheckHandler((webContents, permission) => {
  if (webContents.getURL().startsWith('https://google.com/') && permission === 'notification') {
    return true
  }
  return false
})

// 變更為
session.setPermissionCheckHandler((webContents, permission, requestingOrigin) => {
  if (new URL(requestingOrigin).hostname === 'google.com' && permission === 'notification') {
    return true
  }
  return false
})

已移除:shell.moveItemToTrash()

已廢棄的同步方法 shell.moveItemToTrash() 已移除。 作為替代,您應當使用異步的 shell.trashItem()。

// 在 Electron 13 移除
shell.moveItemToTrash(path)
// 替換為
shell.trashItem(path).then(/* ... */)

已移除: BrowserWindow 擴展 API?

移除已棄用的擴展 API:

  • ?BrowserWindow.addExtension(path)?
  • ?BrowserWindow.addDevToolsExtension(path)?
  • ?BrowserWindow.removeExtension(name)?
  • ?BrowserWindow.removeDevToolsExtension(name)?
  • ?BrowserWindow.getExtensions()?
  • ?BrowserWindow.getDevToolsExtensions()?

改為使用 session API:

  • ?ses.loadExtension(path)?
  • ?ses.removeExtension(extension_id)?
  • ?ses.getAllExtensions()?
// 在 Electron 13 移除
BrowserWindow.addExtension(path)
BrowserWindow.addDevToolsExtension(path)
// 替換為
session.defaultSession.loadExtension(path)
// 在 Electron 13 移除
BrowserWindow.removeExtension(name)
BrowserWindow.removeDevToolsExtension(name)
// 替換為
session.defaultSession.removeExtension(extension_id)
// 在 Electron 13 移除
BrowserWindow.getExtensions()
BrowserWindow.getDevToolsExtensions()
// 替換為
session.defaultSession.getAllExtensions()

已移除: systemPreferences 中的方法

?systemPreferences? 方法已經(jīng)被廢棄:

  • ?systemPreferences.isDarkMode()?
  • ?systemPreferences.isInvertedColorScheme()?
  • ?systemPreferences.isHighContrastColorScheme()?

使用 ?nativeTheme? 屬性作為替代:

  • ?nativeTheme.shouldUseDarkColors?
  • ?nativeTheme.shouldUseInvertedColorScheme?
  • ?nativeTheme.shouldUseHighContrastColors?
// 在 Electron 13 移除
systemPreferences.isDarkMode()
// 替換為
nativeTheme.shouldUseDarkColors

// 在 Electron 13 移除
systemPreferences.isInvertedColorScheme()
// 替換為
nativeTheme.shouldUseInvertedColorScheme

// 在 Electron 13 移除
systemPreferences.isHighContrastColorScheme()
// 替換為
nativeTheme.shouldUseHighContrastColors

已廢棄: WebContents new-window 事件

WebContents 中的 new-window 事件已經(jīng)被廢棄。 已棄用:webContents.setWindowOpenHandler()。

// 在 Electron 13 廢棄
webContents.on('new-window', (event) => {
  event.preventDefault()
})

// 替換為
webContents.setWindowOpenHandler((details) => {
  return { action: 'deny' }
})

Planned Breaking API Changes (12.0)?

已移除:Pepper Flash 支持

Chromium 已經(jīng)取消了對Flash的支持,因此我們必須效仿。 更多詳細信息,請參閱 Chromium 的 Flash Roadmap

默認更改: worldSafeExecuteJavaScript 默認為 true

在 Electron 12, worldSafeExecuteJavaScript 將默認啟用。 要恢復 上一個行為, worldSafeExecuteJavaScript: false 必須在 Web 首選項中指定。 請注意,設(shè)置此選項為 false 是不安全的。

此選項將在 Electron 14 中刪除,所以請遷移您的代碼以支持默認值。

默認更改:contextIsolation 默認為 true

在 Electron 12 中,contextIsolation 將默認啟用。 要恢復 上一個行為, contextIsolation: false 必須在 Web 首選項中指定。

我們建議啟用 contextIsolation 以確保應用程序的安全。

另一個含義是 require() 不能在 renderer process 中使用,除非 nodeIntegration 是 true 和 contextIsolation 是 false.

更多信息請參閱:https://github.com/electron/electron/issues/23506

Removed: crashReporter.getCrashesDirectory()

crashReporter.getCrashesDirectory 方法已被刪除。 這個方法 應該被 app.getPath('crashDumps')替換。

// 在 Electron 12 移除
crashReporter.getCrashesDirectory()
// 替換為
app.getPath('crashDumps')

已移除:渲染進程中的 crashReporter 方法

crashReporter 方法在渲染進程中不再能使用:

  • crashReporter.start
  • crashReporter.getLastCrashReport
  • crashReporter.getUploadedReports
  • crashReporter.getUploadToServer
  • ?crashReporter.setUploadToServer?
  • ?crashReporter.getCrashesDirectory?

它們只應從主要進程中調(diào)用。

更多詳細信息請訪問 #23265

默認值已更改:crashReporter.start({ compress: true })

crashReporter.start 中的 compress 選項的默認值已經(jīng)從 false 改為 true。 這意味著崩潰 dumps 將使用 Content-Encoding: gzip header,上傳到崩潰服務(wù)器,并進行壓縮。

如果 crash 服務(wù)器不支持壓縮負載,則可以通過在 crash reporter 選項中指定 { compress: false } 來 關(guān)閉壓縮。

已廢棄: remote 模塊

remote 模塊在 Electron 12 廢棄,并將在 Electron 14 被移除 由@electronic/remote 模塊替代。

// 在 Electron 12 廢除:
const { BrowserWindow } = require('electron').remote
// 替換為:
const { BrowserWindow } = require('@electron/remote')

// 在主進程中:
require('@electron/remote/main').initialize()

已廢棄:shell.moveItemToTrash()

新的異步shell.trashItem()方法替代了同步的shell.moveItemToTrash()方法。

// 在 Electron 12 廢棄
shell.moveItemToTrash(path)
// 替換為
shell.trashItem(path).then(/* ... */)

Planned Breaking API Changes (11.0)?

移除: BrowserView 中的 BrowserView.{destroy, fromId, fromWebContents, getAllViews} 和 id 屬性

實驗性 API BrowserView.{destroy, fromId, fromWebContents, getAllViews} 現(xiàn)已被移除。 此外, BrowserView 中的 id 屬性也已被移除。

更多信息見 #23578。

Planned Breaking API Changes (10.0)?

已廢棄:crashReporter.start() 中的 companyName 參數(shù)

crashReporter.start() 中的 companyName 參數(shù)之前是必選的,現(xiàn)在是可選的,并且在未來將會被廢棄。 如果要以不推薦的方式獲得相同的行為,可以在 globalExtra 中傳遞 companyName 值。

// 在 Electron 10 廢除
crashReporter.start({ companyName: 'Umbrella Corporation' })
// 替換為
crashReporter.start({ globalExtra: { _companyName: 'Umbrella Corporation' } })

已廢棄:crashReporter.getCrashesDirectory()

crashReporter.getCrashesDirectory 方法已經(jīng)被廢除。 這個方法 應該被 app.getPath('crashDumps')替換。

// 在 Electron 10 廢除
crashReporter.getCrashesDirectory()
// 替換為
app.getPath('crashDumps')

已廢棄:渲染進程中的 crashReporter 方法

從 renderer process 調(diào)用 crashReporter,已經(jīng)被廢棄

  • ?crashReporter.start?
  • ?crashReporter.getLastCrashReport?
  • ?crashReporter.getUploadedReports?
  • ?crashReporter.getUploadToServer?
  • ?crashReporter.setUploadToServer?
  • ?crashReporter.getCrashesDirectory?

在渲染器的 crashReporter 模塊中,未棄用的方法是 addExtraParameter、 removeExtraParameter 和 getParameters。

當從主要進程調(diào)用時,上述所有方法均未被棄用。

更多詳細信息請訪問 #23265

已廢棄:crashReporter.start({ compress: false })

不推薦在 crashReporter.start 中設(shè)置 { compress: false } 幾乎所有的 crash 服務(wù)器都支持 gzip 壓縮。 此選項將在未來版本的 Electron 中刪除。

默認更改: enableRemoteModule 默認為 false

在 Electron 9,如果不在 WebPreferences 中顯式開啟 enableRemoteModule 參數(shù),就使用 remote 模塊,將會開始發(fā)出警告。 在 Electron 10 中,remote 模塊默認處于禁用狀態(tài)。 如果要使用 remote 模塊,必須在 WebPreferences 中指定 enableRemoteModule: true :

const w = new BrowserWindow({
  webPreferences: {
    enableRemoteModule: true
  }
})

我們 建議遠離 remote 模塊。

protocol.unregisterProtocol?

protocol.uninterceptProtocol?

這些 APIs 現(xiàn)在是同步的,不再需要可選的回調(diào)。

// 已廢棄
protocol.unregisterProtocol(scheme, () => { /* ... */ })
// 替換為
protocol.unregisterProtocol(scheme)

protocol.registerFileProtocol?

protocol.registerBufferProtocol?

protocol.registerStringProtocol?

protocol.registerHttpProtocol?

protocol.registerStreamProtocol?

protocol.interceptFileProtocol?

protocol.interceptStringProtocol?

protocol.interceptBufferProtocol?

protocol.interceptHttpProtocol?

protocol.interceptStreamProtocol?

這些 APIs 現(xiàn)在是同步的,不再需要可選的回調(diào)。

// 已廢棄
protocol.registerFileProtocol(scheme, handler, () => { /* ... */ })
// 替換為
protocol.registerFileProtocol(scheme, handler)

在導航發(fā)生之前,注冊或攔截的 protocol 不會對當前頁面產(chǎn)生影響。

protocol.isProtocolHandled

此 API 已廢棄,用戶應該使用 protocol.isProtocolRegistered 和 protocol.isProtocolIntercepted

// 廢棄
protocol.isProtocolHandled(scheme).then(() => { /* ... */ })
// 替換為
const isRegistered = protocol.isProtocolRegistered(scheme)
const isIntercepted = protocol.isProtocolIntercepted(scheme)

計劃重寫的 API (9.0)?

默認更改:默認在 renderer process 中禁用加載 non-context-aware native modules?

從Electron 9開始,我們不允許在 renderer process 加載 non-context-aware native modules。 這是為了提高 Electron 作為一個項目的安全性、性能性和維護性。

如果這對你有影響,你可以臨時將 app.allowRendererProcessReuse 設(shè)置為 false,這將恢復到舊的行為。 在 Electron 11 之前,此標志只是一個選項,因此你應該計劃更換你的 native modules 模塊,已進行 context aware。

有關(guān)更多詳細信息,請參閱 #18397.

已廢棄: BrowserWindow 擴展 API?

以下擴展 APIs 已廢棄:

  • ?BrowserWindow.addExtension(path)?
  • ?BrowserWindow.addDevToolsExtension(path)?
  • ?BrowserWindow.removeExtension(name)?
  • ?BrowserWindow.removeDevToolsExtension(name)?
  • ?BrowserWindow.getExtensions()?
  • ?BrowserWindow.getDevToolsExtensions()?

改為使用 session API:

  • ?ses.loadExtension(path)?
  • ?ses.removeExtension(extension_id)?
  • ?ses.getAllExtensions()?
// 在 Electron 9 廢棄
BrowserWindow.addExtension(path)
BrowserWindow.addDevToolsExtension(path)
// 替換為
session.defaultSession.loadExtension(path)
// 在 Electron 9 廢棄
BrowserWindow.removeExtension(name)
BrowserWindow.removeDevToolsExtension(name)
// 替換為
session.defaultSession.removeExtension(extension_id)
// 在 Electron 9 廢棄
BrowserWindow.getExtensions()
BrowserWindow.getDevToolsExtensions()
// 替換為
session.defaultSession.getAllExtensions()

已移除: <webview>.getWebContents()?

此API在 Electron 8.0中被廢棄,現(xiàn)已刪除。

// 在 Electron 9.0 移除
webview.getWebContents()
// 替換為
const { remote } = require('electron')
remote.webContents.fromId(webview.getWebContentsId())

已移除:webFrame.setLayoutZoomLevelLimits()?

Chromium 已經(jīng)取消了對更改布局縮放級別限制的支持,它超出了 Electron 維護它的能力。 此函數(shù)在 Electron 8.x 廢棄,并將在 Electron 9.x 被移除。 布局縮放級別限制現(xiàn)在已固定為最小 0.25 最大 5.0,定義在: 這里

行為改變: 通過 IPC 發(fā)送非 JS 對象,現(xiàn)在將引發(fā)異常

在 Electron 8.0 中, IPC 被更改為使用結(jié)構(gòu)化克隆算法(Structured Clone Algorithm),顯著提高了性能。 為了幫助簡化轉(zhuǎn)換,保留了舊的 IPC 序列化算法,并將其用于一些無法通過結(jié)構(gòu)化克隆序列化的對象。 特別是 DOM 對象(例如:Element、Location、DOMMatrix),Node.js 中由 C++ 類支持的對象(例如:process.env、Stream 中的一些方法),和 Electron 中由 C++ 類支持的對象(例如:WebContents、BrowserWindowWebFrame)無法使用使用結(jié)構(gòu)化克隆序列化。 每當調(diào)用到舊算法時,都會打印棄用警告。

在 Electron 9 中,舊的序列化算法已被刪除,并且此類不可序列化的對象現(xiàn)在將會拋出一個“object could not be cloned”(對象無法被克?。?錯誤。

API 變化:shell.openItem 變化為 shell.openPath

shell.openItem API 已被替換成異步的 shell.openPath API。 你可以在這里查看原始 API 提案和推理

計劃重寫的 API (8.0)?

行為改變:通過 IPC 發(fā)送的值現(xiàn)在已經(jīng)使用結(jié)構(gòu)化克?。⊿tructured Clone Algorithm)算法進行序列化。

用于序列化通過 IPC 發(fā)送的對象(通過 ipcRenderer.send、ipcRenderer.sendSyncWebContents.send 以及相關(guān)方法)已經(jīng)從自定義算法切換到 V8 內(nèi)置的 結(jié)構(gòu)化克隆算法,和 postMessage 使用序列化消息的算法相同。 這將為大型消息帶來了 2 倍的性能改進,但也帶來一些行為上的重大變化。

  • 通過 IPC 發(fā)送的 Function、Promise、WeakMaps、WeakSets 或者包含任何此類值的對象現(xiàn)在將引發(fā)異常,而不是靜默地將函數(shù)轉(zhuǎn)換為 ?undefined?
// 之前:
ipcRenderer.send('channel', { value: 3, someFunction: () => {} })
// => results in { value: 3 } arriving in the main process

// 從 Electron 8 開始:
ipcRenderer.send('channel', { value: 3, someFunction: () => {} })
// => throws Error("() => {} could not be cloned.")
  • NaNInfinity、-Infinity 現(xiàn)在將被正確的序列化,而不是轉(zhuǎn)換為 null。
  • 包含循環(huán)引用的對象現(xiàn)在將被正確的序列化,而不是轉(zhuǎn)換為 null。
  • Set、MapError、RegExp 值將被正確的序列化,而不是轉(zhuǎn)換為 {}。
  • BigInt 值將被正確的序列化,而不是轉(zhuǎn)換為 null
  • Sparse 數(shù)組將按照本身去序列化,而不是轉(zhuǎn)換為具有 null 的數(shù)組。
  • Date 對象將被轉(zhuǎn)換成 Date 對象,而不是轉(zhuǎn)換成 ISO 字符串表達形式。
  • 類型化數(shù)組(例如 ?Uint8Array?、?Uint16Array?、?Uint32Array? 等)將按原樣傳輸,而不是轉(zhuǎn)換為 Node.js 緩沖區(qū)。

  • Node.js Buffer 對象將作為 ?Uint8Arrays? 傳輸。您可以通過包裝底層 ArrayBuffer 將 ?Uint8Array? 轉(zhuǎn)換回 Node.js 緩沖區(qū):

Buffer.from(value.buffer, value.byteOffset, value.byteLength)

發(fā)送任何非原生 JS 類型的對象,例如 DOM 對象(例如 Element、Location、DOMMatrix)、Node.js 對象(例如 process.env、Stream)或 Electron 對象(例如 WebContents、BrowserWindow、WebFrame)已被棄用.在 Electron 8 中,這些對象將像以前一樣使用 DeprecationWarning 消息進行序列化,但從 Electron 9 開始,發(fā)送這些類型的對象將拋出“無法克隆”錯誤。

已廢棄: <webview>.getWebContents()

該 API 是使用 remote 模塊實現(xiàn)的,它同時具有性能和安全隱患。因此它的用法應該是明確的。

// Deprecated
webview.getWebContents()
// Replace with
const { remote } = require('electron')
remote.webContents.fromId(webview.getWebContentsId())

然而,建議完全避免使用 remote 模塊

// main
const { ipcMain, webContents } = require('electron')

const getGuestForWebContents = (webContentsId, contents) => {
  const guest = webContents.fromId(webContentsId)
  if (!guest) {
    throw new Error(`Invalid webContentsId: ${webContentsId}`)
  }
  if (guest.hostWebContents !== contents) {
    throw new Error('Access denied to webContents')
  }
  return guest
}

ipcMain.handle('openDevTools', (event, webContentsId) => {
  const guest = getGuestForWebContents(webContentsId, event.sender)
  guest.openDevTools()
})

// renderer
const { ipcRenderer } = require('electron')

ipcRenderer.invoke('openDevTools', webview.getWebContentsId())

Deprecated: webFrame.setLayoutZoomLevelLimits()

Chromium 已經(jīng)取消了對更改布局縮放級別限制的支持,它超出了 Electron 維護它的能力。 該函數(shù)將在 Electron 8.x 中發(fā)出警告,并在 Electron 9.x 中不復存在。布局縮放級別限制現(xiàn)在固定為最小 0.25 和最大 5.0,如此處所定義。

Deprecated events in systemPreferences

systemPreferences 事件已經(jīng)被廢棄:

  • ?inverted-color-scheme-changed?
  • ?high-contrast-color-scheme-changed?

改用 nativeTheme 模塊上的新更新事件。

// Deprecated
systemPreferences.on('inverted-color-scheme-changed', () => { /* ... */ })
systemPreferences.on('high-contrast-color-scheme-changed', () => { /* ... */ })

// Replace with
nativeTheme.on('updated', () => { /* ... */ })

已廢棄:systemPreferences 中的方法

systemPreferences 方法已經(jīng)被廢棄:

  • ?systemPreferences.isDarkMode()?
  • ?systemPreferences.isInvertedColorScheme()?
  • ?systemPreferences.isHighContrastColorScheme()?

使用 ?nativeTheme? 屬性作為替代:

  • ?nativeTheme.shouldUseDarkColors?
  • ?nativeTheme.shouldUseInvertedColorScheme?
  • ?nativeTheme.shouldUseHighContrastColors?
// 已廢棄
systemPreferences.isDarkMode()
// 替換為
nativeTheme.shouldUseDarkColors

// 已廢棄
systemPreferences.isInvertedColorScheme()
// 替換為
nativeTheme.shouldUseInvertedColorScheme

// 已廢棄
systemPreferences.isHighContrastColorScheme()
// 替換為
nativeTheme.shouldUseHighContrastColors

重大的API更新 (7.0)?

Deprecated: Atom.io Node Headers URL

這是在構(gòu)建原生 node 模塊時在 .npmrc 文件中指定為 disturl 的 url 或是 --dist-url 命令行標志. Both will be supported for the foreseeable future but it is recommended that you switch.

Deprecated: https://atom.io/download/electron

Replace with: https://electronjs.org/headers

API Changed: session.clearAuthCache() no longer accepts options

?session.clearAuthCache? API 不再接受清除內(nèi)容的選項,而是無條件清除整個緩存。

// Deprecated
session.clearAuthCache({ type: 'password' })
// Replace with
session.clearAuthCache()

API Changed: powerMonitor.querySystemIdleState is now powerMonitor.getSystemIdleState

// Removed in Electron 7.0
powerMonitor.querySystemIdleState(threshold, callback)
// Replace with synchronous API
const idleState = powerMonitor.getSystemIdleState(threshold)

API Changed: powerMonitor.querySystemIdleTime is now powerMonitor.getSystemIdleTime

// Removed in Electron 7.0
powerMonitor.querySystemIdleTime(callback)
// Replace with synchronous API
const idleTime = powerMonitor.getSystemIdleTime()

API Changed: webFrame.setIsolatedWorldInfo replaces separate methods

// Removed in Electron 7.0
webFrame.setIsolatedWorldContentSecurityPolicy(worldId, csp)
webFrame.setIsolatedWorldHumanReadableName(worldId, name)
webFrame.setIsolatedWorldSecurityOrigin(worldId, securityOrigin)
// Replace with
webFrame.setIsolatedWorldInfo(
  worldId,
  {
    securityOrigin: 'some_origin',
    name: 'human_readable_name',
    csp: 'content_security_policy'
  })

Removed: marked property on getBlinkMemoryInfo?

此屬性在 Chromium 77 中已被刪除,因此不再可用。

Behavior Changed: webkitdirectory attribute for <input type="file"/> now lists directory contents

HTML 文件輸入的 webkitdirectory 屬性允許他們選擇文件夾。 Electron 的早期版本有一個不正確的實現(xiàn),其中輸入的 event.target.files 返回一個 FileList,該 FileList 返回一個與所選文件夾對應的文件。

從 Electron 7 開始,該 FileList 現(xiàn)在是文件夾中包含的所有文件的列表,類似于 Chrome、Firefox 和 Edge(鏈接到 MDN 文檔)。

作為說明,以具有以下結(jié)構(gòu)的文件夾為例:

folder
├── file1
├── file2
└── file3

在 Electron <=6 中,這將返回一個 FileList 與一個 File 對象:

path/to/folder

在 Electron 7 中,這現(xiàn)在返回一個 FileList 和一個 File 對象:

/path/to/folder/file3
/path/to/folder/file2
/path/to/folder/file1

請注意,webkitdirectory 不再公開所選文件夾的路徑。

API Changed: Callback-based versions of promisified APIs?

Electron 5 和 Electron 6 引入了現(xiàn)有異步 API 的基于 Promise 的版本,并棄用了它們較舊的基于回調(diào)的對應版本。在 Electron 7 中,所有已棄用的基于回調(diào)的 API 現(xiàn)已被刪除。

這些函數(shù)現(xiàn)在只返回 Promises:

  • app.getFileIcon() #15742
  • app.dock.show() #16904
  • contentTracing.getCategories() #16583
  • contentTracking.getTraceBufferUs() #16600
  • contentTracing.startRecording() #16584
  • contentTracing.stopRecording() #16584
  • contents.executeJavaScript() #17312
  • cookies.flushStore() #16464
  • cookies.get() #16464
  • cookies.remove() #16464
  • cookies.set() #16464
  • debugger.sendCommand() #16861
  • dialog.showCertificateTrustDialog() #17181
  • inAppPurchase.getProducts() #17355
  • inAppPurchase.purchaseProduct()#17355
  • netLog.stopLogging() #16862
  • session.clearAuthCache() #17259
  • session.clearCache() #17185
  • session.clearHostResolverCache() #17229
  • session.clearStorageData() #17249
  • session.getBlobData() #17303
  • session.getCacheSize() #17185
  • session.resolveProxy() #17222
  • session.setProxy() #17222
  • shell.openExternal() #16176
  • webContents.loadFile() #15855
  • webContents.loadURL() #15855
  • webContents.hasServiceWorker() #16535
  • webContents.printToPDF() #16795
  • webContents.savePage() #16742
  • webFrame.executeJavaScript() #17312
  • webFrame.executeJavaScriptInIsolatedWorld() #17312
  • webviewTag.executeJavaScript() #17312
  • win.capturePage() #15743

這些功能現(xiàn)在有兩種形式,即同步和基于Promise的異步:

  • dialog.showMessageBox()/dialog.showMessageBoxSync() #17298
  • dialog.showOpenDialog()/dialog.showOpenDialogSync() #16973
  • dialog.showSaveDialog()/dialog.showSaveDialogSync() #17054

重大的API更新 (6.0)?

API Changed: win.setMenu(null) is now win.removeMenu()

// 不推薦
win.setMenu(null)
// 替換為
win.removeMenu()

API Changed: electron.screen in the renderer process should be accessed via remote

// 不推薦
require('electron').screen
// 替換為
require('electron').remote.screen

API Changed: require()ing node builtins in sandboxed renderers no longer implicitly loads the remote version

// 不推薦
require('child_process')
// 替換為
require('electron').remote.require('child_process')

// 不推薦
require('fs')
// 替換為
require('electron').remote.require('fs')

// 不推薦
require('os')
// 替換為
require('electron').remote.require('os')

// 不推薦
require('path')
// 替換為
require('electron').remote.require('path')

Deprecated: powerMonitor.querySystemIdleState replaced with powerMonitor.getSystemIdleState

// 廢棄
powerMonitor.querySystemIdleState(threshold, callback)
// 替換為 synchronous API
const idleState = powerMonitor.getSystemIdleState(threshold)

Deprecated: powerMonitor.querySystemIdleTime replaced with powerMonitor.getSystemIdleTime

// 廢棄
powerMonitor.querySystemIdleTime(callback)
// 替換為 synchronous API
const idleTime = powerMonitor.getSystemIdleTime()

Deprecated: app.enableMixedSandbox() is no longer needed

// 廢棄
app.enableMixedSandbox()

混合沙盒模式已默認啟用。

Deprecated: Tray.setHighlightMode

在 macOS Catalina 下,我們之前的 Tray 實現(xiàn)中斷了。 Apple 的原生替代品不支持更改突出顯示行為。

// 廢棄
tray.setHighlightMode(mode)
// API will be removed in v7.0 without replacement.

重大的API更新 (5.0)?

Default Changed: nodeIntegration and webviewTag default to false, contextIsolation defaults to true

不推薦使用以下 webPreferences 選項默認值,以支持下面列出的新默認值。

屬性 不推薦使用的默認值 新的默認值
contextIsolation false true
nodeIntegration true false
webviewTag nodeIntegration 未設(shè)置過則是 true false

如下: 重新開啟 webviewTag

const w = new BrowserWindow({
  webPreferences: {
    webviewTag: true
  }
})

Behavior Changed: nodeIntegration in child windows opened via nativeWindowOpen?

使用 nativeWindowOpen 選項打開的子窗口將始終禁用 Node.js 集成,除非 nodeIntegrationInSubFrames 為真。

API Changed: Registering privileged schemes must now be done before app ready

渲染器進程 API webFrame.registerURLSchemeAsPrivileged 和 webFrame.registerURLSchemeAsBypassingCSP 以及瀏覽器進程 API protocol.registerStandardSchemes 已被刪除。新的 API protocol.registerSchemeasviliged 已被添加,并用于注冊具有必要權(quán)限的自定義 scheme。 自定義 scheme 需要在 app 觸發(fā) ready 事件之前注冊。

已廢棄: webFrame.setIsolatedWorld* 已替換為 webFrame.setIsolatedWorldInfo

// 棄用
webFrame.setIsolatedWorldContentSecurityPolicy(worldId, csp)
webFrame.setIsolatedWorldHumanReadableName(worldId, name)
webFrame.setIsolatedWorldSecurityOrigin(worldId, securityOrigin)
// 替換為
webFrame.setIsolatedWorldInfo(
  worldId,
  {
    securityOrigin: 'some_origin',
    name: 'human_readable_name',
    csp: 'content_security_policy'
  })

API Changed: webFrame.setSpellCheckProvider now takes an asynchronous callback?

spellCheck 回調(diào)現(xiàn)在是異步的,并且 autoCorrectWord 參數(shù)已被刪除。

// Deprecated
webFrame.setSpellCheckProvider('en-US', true, {
  spellCheck: (text) => {
    return !spellchecker.isMisspelled(text)
  }
})
// Replace with
webFrame.setSpellCheckProvider('en-US', {
  spellCheck: (words, callback) => {
    callback(words.filter(text => spellchecker.isMisspelled(text)))
  }
})

API Changed: webContents.getZoomLevel and webContents.getZoomFactor are now synchronous?

webContents.getZoomLevel 和 webContents.getZoomFactor 不再接受回調(diào)參數(shù),而是直接返回它們的數(shù)值。

// 廢棄
webContents.getZoomLevel((level) => {
  console.log(level)
})
// 替換成
const level = webContents.getZoomLevel()
console.log(level)
// 廢棄
webContents.getZoomFactor((factor) => {
  console.log(factor)
})
// 替換成
const factor = webContents.getZoomFactor()
console.log(factor)

計劃重寫的 API (4.0)?

以下列表包含了Electron4.0中重大的API更新

app.makeSingleInstance

// 已廢棄
app.makeSingleInstance((argv, cwd) => {
  /* ... */
})
// 替換為
app.requestSingleInstanceLock()
app.on('second-instance', (event, argv, cwd) => {
  /* ... */
})

app.releaseSingleInstance

// 廢棄
app.releaseSingleInstance()
// 替換為
app.releaseSingleInstanceLock()

app.getGPUInfo

app.getGPUInfo('complete')
// 現(xiàn)在的行為將與macOS下的`basic`設(shè)置一樣
app.getGPUInfo('basic')

win_delay_load_hook

在為 Windows 構(gòu)建本機模塊時,將使 win_delay_load_hook 變量值 位于 binding.gyp 模塊,必須為 true (這是默認值)。 如果這個鉤子 不存在,那么本機模塊將無法在 Windows 上加載,并出現(xiàn)錯誤 消息如 無法找到模塊。

移除: IA32 Linux 支持?

Electron 18 將不再支持在 32 位 Linux 系統(tǒng)上運行。

重大的API更新 (3.0)?

以下包含了Electron 3.0中重大的API更新

app

// 棄用
app.getAppMemoryInfo()
// 替換為
app.getAppMetrics()

// 棄用
const metrics = app.getAppMetrics()
const { memory } = metrics[0] // 棄用的屬性

BrowserWindow

// 已廢棄
const optionsA = { webPreferences: { blinkFeatures: '' } }
const windowA = new BrowserWindow(optionsA)
// 替換為
const optionsB = { webPreferences: { enableBlinkFeatures: '' } }
const windowB = new BrowserWindow(optionsB)

// 已廢棄
window.on('app-command', (e, cmd) => {
  if (cmd === 'media-play_pause') {
    // do something
  }
})
// 替換為
window.on('app-command', (e, cmd) => {
  if (cmd === 'media-play-pause') {
    // do something
  }
})

clipboard

// 過時的
clipboard.readRtf()
// 替換為
clipboard.readRTF()

// 過時的
clipboard.writeRtf()
// 替換為
clipboard.writeRTF()

// 過時的
clipboard.readHtml()
// 替換為
clipboard.readHTML()

// 過時的
clipboard.writeHtml()
//替換為
clipboard.writeHTML()

crashReporter

// 過時的
crashReporter.start({
  companyName: 'Crashly',
  submitURL: 'https://crash.server.com',
  autoSubmit: true
})
// 替換為
crashReporter.start({
  companyName: 'Crashly',
  submitURL: 'https://crash.server.com',
  uploadToServer: true
})

nativeImage

// 棄用
nativeImage.createFromBuffer(buffer, 1.0)
// 替換為
nativeImage.createFromBuffer(buffer, {
  scaleFactor: 1.0
})

process

// 棄用
const info = process.getProcessMemoryInfo()

screen

// 棄用
screen.getMenuBarHeight()
// 替換為
screen.getPrimaryDisplay().workArea

session

// 棄用
ses.setCertificateVerifyProc((hostname, certificate, callback) => {
  callback(true)
})
// 替換為
ses.setCertificateVerifyProc((request, callback) => {
  callback(0)
})

Tray

// 過時的
tray.setHighlightMode(true)
// 替換為
tray.setHighlightMode('on')

// 過時的
tray.setHighlightMode(false)
// 替換為
tray.setHighlightMode('off')

webContents

// 棄用
webContents.openDevTools({ detach: true })
// 替換為
webContents.openDevTools({ mode: 'detach' })

// 移除
webContents.setSize(options)
// 沒有該API的替代

webFrame

// 棄用
webFrame.registerURLSchemeAsSecure('app')
// 替換為
protocol.registerStandardSchemes(['app'], { secure: true })

// 棄用
webFrame.registerURLSchemeAsPrivileged('app', { secure: true })
// 替換為
protocol.registerStandardSchemes(['app'], { secure: true })

<webview>

// 移除
webview.setAttribute('disableguestresize', '')
// 沒有該API的替代

// 移除
webview.setAttribute('guestinstance', instanceId)
// 沒有該API的替代

// 鍵盤監(jiān)聽器在webview標簽中不再起效
webview.onkeydown = () => { /* handler */ }
webview.onkeyup = () => { /* handler */ }

Node Headers URL

這是在構(gòu)建原生 node 模塊時在 .npmrc 文件中指定為 disturl 的 url 或是 --dist-url 命令行標志.

過時的: https://atom.io/download/atom-shell

替換為: https://atom.io/download/electron

重大的API更新 (2.0)?

以下包含了Electron 2.0中重大的API更新

BrowserWindow

// 已廢棄
const optionsA = { titleBarStyle: 'hidden-inset' }
const windowA = new BrowserWindow(optionsA)
// 替換為
const optionsB = { titleBarStyle: 'hiddenInset' }
const windowB = new BrowserWindow(optionsB)

menu

// 移除
menu.popup(browserWindow, 100, 200, 2)
// 替換為
menu.popup(browserWindow, { x: 100, y: 200, positioningItem: 2 })

nativeImage

// 移除
nativeImage.toPng()
// 替換為
nativeImage.toPNG()

// 移除
nativeImage.toJpeg()
// 替換為
nativeImage.toJPEG()

process

  • process.versions.electronprocess.version.chrome 將成為只讀屬性, 以便與其他 process.versions 屬性由Node設(shè)置。

webContents

// 移除
webContents.setZoomLevelLimits(1, 2)
// 替換為
webContents.setVisualZoomLevelLimits(1, 2)

webFrame

// 被廢棄
webFrame.setZoomLevelLimits(1, 2)
// 替換為
webFrame.setVisualZoomLevelLimits(1, 2)

<webview>

// 移除
webview.setZoomLevelLimits(1, 2)
// 替換為
webview.setVisualZoomLevelLimits(1, 2)

重復的 ARM 資源

每個 Electron 發(fā)布版本包含兩個相同的ARM版本,文件名略有不同,如electron-v1.7.3-linux-arm.zip 和 electron-v1.7.3-linux-armv7l.zip 添加包含v7l前綴的資源向用戶明確其支持的ARM版本,并消除由未來armv6l 和 arm64 資源可能產(chǎn)生的歧義。

沒有前綴的文件仍在發(fā)布,以避免破壞可能使用它的任何設(shè)置。從2.0版本起,不帶前綴的文件將不再發(fā)布。

更多詳細情況,查看 6986 和 7189


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號