Posted at

<webview>からBrowserViewへの移行

これは Gotanda.js #12 in ZEALS で発表した内容からTIPSを抜き出した記事です。

元Slide: https://speakerdeck.com/nekobato/migration-to-browserwindow-in-electron


package.json

{

"dependencies": {
"electron": "5.0.4",
},
}

Electron公式ではBrowserView<webview>の代わりに使うことを推奨しています。

BrowserViewは可能な操作が<webview>に比べてまだ少なく、またmain process上で管理するため、<webview>とは些か勝手が違ってきます。

ここでは、BrowserView<webview>を操作してきた手法を置換するためのTIPSを紹介します。


基本的な操作

Before


webview.js

const webview = document.querySelector('webview');

// 表示するWeb Pageを変更する
webview.src = 'https://yahoo.co.jp';

// 戻れるなら戻る
if (webview.canGoBack()) {
webview.goBack();
}

// いけたらいく
if (webview.canGoForward()) {
webview.goForward();
}

// 更新
webview.reload();


After


BrowserView-renderer.js

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

ipcRenderer.send('SET_URL', { url: 'https://yahoo.co.jp' });
ipcRenderer.send('BACK');
ipcRenderer.send('FORWARD');
ipcRenderer.send('RELOAD');



BrowserView-main.js

ipcMain.on('SET_URL', (_, payload) => {

webView.webContents.loadURL(payload.url);
});

ipcMain.on('BACK', () => {
if (webView.webContents.canGoBack()) {
webView.webContents.goBack();
}
});

ipcMain.on('FORWARD', () => {
if (webView.webContents.canGoForward()) {
webView.webContents.goForward();
}
});

ipcMain.on('RELOAD', () => {
webView.webContents.reload();
});


基本的にRendererとコミュニケーションしたい場合はイベントを送るという手法を採用しています。


URLの変更をRendererで検知する

function setUrl(url: string): void {

mainWindow.webContents.send(types.SET_URL, {
url,
// ついでにcanGoBackとcanGoForwardを報告する
canGoBack: webView.webContents.canGoBack(),
canGoForward: webView.webContents.goForward(),
});
}

webView.webContents.on('did-navigate', (_, url) => {
setUrl(url);
});

webView.webContents.on('did-navigate-in-page', (_, url) => {
setUrl(url);
});


サイズを可変にする


ウィンドウサイズに合わせて可変にする


BrowserView-main.js

mainWindow.on('will-resize', (_, { width, height }) => {

webView.setBounds({
x: 0,
y: 0,
width,
height,
});
});


レイアウトに合わせて可変にする


BrowserView-renderer.js

const webviewArea = document.querySelector('.webview-area');

ipcRendeerer.send('SET_BOUNDS', {
x: webviewArea.offsetLeft,
y: webviewArea.offsetTop,
width: webviewArea.innerWidth,
height: webviewArea.innerHeight
});


BrowserView-main.js

ipcMain.on('SET_BOUNDS', (_, { x, y, width, height }) => {

webView.setBounds({
x,
y,
width,
height
});
});


DevToolsを開く時に邪魔なので隠す

BrowserViewはWebおよびDevToolsよりも上に重なって表示されるため、BrowserWindowに表示されているWebのデバッグ中は邪魔です。DevToolsを表示中は隠す処理を書いておくと便利です。


BrowserView-main.js

mainWindow.webContents.on('devtools-opened', () => {

webView.setBounds({
x,
y,
// hide() みたいな便利な関数は無いので、見えないようにサイズ変更する
0,
0
});
});

mainWindow.webContents.on('devtools-closed', () => {
webView.setBounds({
x,
y,
defaultWidth,
defaultHeight
});
});



BrowserViewの見た目をCSSで変えたい

無理だよ