{"id":2685,"date":"2021-05-09T11:37:39","date_gmt":"2021-05-09T02:37:39","guid":{"rendered":"https:\/\/www.oqiita.com\/?p=2685"},"modified":"2021-05-09T11:37:39","modified_gmt":"2021-05-09T02:37:39","slug":"%e3%80%90electron-next-js%e3%80%91contextbridge%e4%bd%bf%e3%81%a3%e3%81%a6%e5%8f%b3%e3%82%af%e3%83%aa%e3%83%83%e3%82%af%e3%83%a1%e3%83%8b%e3%83%a5%e3%83%bc-contextmenu","status":"publish","type":"post","link":"https:\/\/www.oqiita.com\/?p=2685","title":{"rendered":"\u3010Electron + Next.js\u3011contextBridge\u4f7f\u3063\u3066\u53f3\u30af\u30ea\u30c3\u30af\u30e1\u30cb\u30e5\u30fc (ContextMenu)"},"content":{"rendered":"<p>\u7a81\u7136\u59cb\u3081\u305f\u304b\u3089\u521d\u5fc3\u8005\u30ec\u30d9\u30eb\u3084\u3067\u3002<\/p>\n<p><!--more--><\/p>\n<p>\u9069\u5f53\u306b\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u4f5c\u3063\u3066\u3001\u3053\u3093\u306a\u753b\u9762\u3092\u4f5c\u6210\u3002<br \/>\n\uff08\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u4f5c\u6210\u65b9\u6cd5\u3068\u304b\u306f\u4f55\u304c\u3044\u3044\u306e\u304b\u77e5\u3089\u306a\u3044\u306e\u3067\u5272\u611b\uff09<br \/>\n<a href=\"https:\/\/www.oqiita.com\/wp-content\/uploads\/2021\/05\/001.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2694\" src=\"https:\/\/www.oqiita.com\/wp-content\/uploads\/2021\/05\/001.png\" alt=\"\" width=\"513\" height=\"605\" srcset=\"https:\/\/www.oqiita.com\/wp-content\/uploads\/2021\/05\/001.png 513w, https:\/\/www.oqiita.com\/wp-content\/uploads\/2021\/05\/001-254x300.png 254w\" sizes=\"auto, (max-width: 513px) 100vw, 513px\"><\/a><\/p>\n<p>\u3044\u308d\u3044\u308d\u691c\u7d22\u3059\u308b\u3068\u3060\u3044\u305f\u3044\u30ec\u30f3\u30c0\u30e9\u30fc\u30d7\u30ed\u30bb\u30b9\uff08HTML\uff09\u306e\u307b\u3046\u3067Node\u306e\u6a5f\u80fd\uff08\u4e3b\u306bremote\uff09\u3092\u547c\u3073\u51fa\u3057\u3066\u308b\u3093\u3060\u3051\u3069\u3001<br \/>\n\u73fe\u5728\u306f\u30c7\u30d5\u30a9\u30eb\u30c8\u3067\u975e\u63a8\u5968\u3089\u3057\u3044\u306e\u3067contextBridge\u3092\u4f7f\u3063\u3066\u3001\u306a\u3093\u3067\u3082\u30e1\u30a4\u30f3\u30d7\u30ed\u30bb\u30b9\u3067\u52d5\u304b\u3059\u5fc5\u8981\u304c\u3042\u308b\u3089\u3057\u3044\u3002<br \/>\n\u307e\u3041\u305d\u308a\u3083\u30ec\u30f3\u30c0\u30e9\u30fc\u306e\u307b\u3046\u3067\u306a\u3093\u3067\u3082\u5b9f\u884c\u3055\u308c\u305f\u3089\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u7684\u306b\u3042\u3076\u306a\u3044\u3057\u3002<\/p>\n<h3 id=\"i-0\">\u30dc\u30bf\u30f3\u3067\u30c0\u30a4\u30a2\u30ed\u30b0<\/h3>\n<p>\u3068\u308a\u3042\u3048\u305a\u30dc\u30bf\u30f3\u62bc\u3057\u305f\u3089\u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u51fa\u3059\u3002<br \/>\ncontextBridge\u306b\u95a2\u3057\u3066\u306f\u4ee5\u4e0b\u306e\u30da\u30fc\u30b8\u304c\u3059\u3054\u304f\u53c2\u8003\u306b\u306a\u308a\u307e\u3057\u305f\u3002<br \/>\n<a href=\"https:\/\/blog.katsubemakito.net\/nodejs\/electron\/ipc-for-contextbridge\" target=\"_blank\" rel=\"noopener\">https:\/\/blog.katsubemakito.net\/nodejs\/electron\/ipc-for-contextbridge<\/a><\/p>\n<p>\u307e\u305a\u306fpreload.js\u3092\u4f5c\u6210\u3057\u3066\u3001\u30ec\u30f3\u30c0\u30e9\u30fc \u2192 \u30e1\u30a4\u30f3\u3092\u4f5c\u6210\u3002\u540d\u524d\u306f\u9069\u5f53\u306b\u300cdialogMsg\u300d\u306b\u3057\u3066\u307e\u3059\u3002<\/p>\n<div class=\"pre_tag\"><span><i class=\"fa fa-code\"><\/i> preload.js<\/span><\/p>\n<pre class=\"line-numbers\"><code class=\"language-js\">const { ipcRenderer, contextBridge } = require(\"electron\");\n\ncontextBridge.exposeInMainWorld(\"electron\", {\n  \/\/ \u30ec\u30f3\u30c0\u30e9\u30fc \u2192 \u30e1\u30a4\u30f3\n  dialogMsg: async (data) =&gt; await ipcRenderer.invoke(\"dialogMsg\", data),\n});\n<\/code><\/pre>\n<\/div>\n<p>\u30e1\u30a4\u30f3\u30d7\u30ed\u30bb\u30b9\u5074\u306eindex.js\u306fipcMain\u3067\u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u51fa\u3059\u51e6\u7406\u3092\u4f5c\u6210\u3002<\/p>\n<div class=\"pre_tag\"><span><i class=\"fa fa-code\"><\/i> \u30e1\u30a4\u30f3\u30d7\u30ed\u30bb\u30b9 \u2013 index.js<\/span><\/p>\n<pre class=\"line-numbers\"><code class=\"language-js\">\/\/ Native\nconst { join } = require(\"path\");\nconst { format } = require(\"url\");\n\n\/\/ Packages\nconst { BrowserWindow, app, ipcMain, dialog} = require(\"electron\");\nconst isDev = require(\"electron-is-dev\");\nconst prepareNext = require(\"electron-next\");\n\n\/\/ Prepare the renderer once the app is ready\napp.on(\"ready\", async () =&gt; {\n  await prepareNext(\".\/renderer\");\n\n  \/\/ \u30a6\u30a3\u30f3\u30c9\u30a6\u4f5c\u6210\n  const mainWindow = new BrowserWindow({\n    width: 800,\n    height: 600,\n    webPreferences: {\n      nodeIntegration: false,\n      contextIsolation: true,\n      preload: join(__dirname, \"preload.js\"),\n    },\n  });\n\n  \/\/ URL\u4f5c\u6210\n  const url = isDev\n    ? \"http:\/\/localhost:8000\"\n    : format({\n        pathname: join(__dirname, \"..\/renderer\/out\/index.html\"),\n        protocol: \"file:\",\n        slashes: true,\n      });\n\n  if (isDev) {\n    \/\/ \u958b\u767a\u8005\u30c4\u30fc\u30eb\n    mainWindow.webContents.openDevTools();\n  }\n\n  mainWindow.loadURL(url);\n});\n\n\/\/ \u7d42\u4e86\u51e6\u7406\napp.on(\"window-all-closed\", app.quit);\n\n\/\/ \u4ee5\u4e0b\u30ec\u30f3\u30c0\u30fc\u3068\u306e\u901a\u4fe1\nipcMain.handle(\"dialogMsg\", (event, data) =&gt; {\n  const w = BrowserWindow.getFocusedWindow();\n  dialog.showMessageBox(w, {\n    type: \"info\",\n    title: \"\u30bf\u30a4\u30c8\u30eb\",\n    message: data,\n  });\n  return;\n});<\/code><\/pre>\n<\/div>\n<p>\u30ec\u30f3\u30c0\u30e9\u30fc\u30d7\u30ed\u30bb\u30b9\u5074\u306eindex.js\u3067\u306fonClick\u30a4\u30d9\u30f3\u30c8\u3067dialogAction\u3092\u547c\u3073\u51fa\u3057\u3066\u3001<br \/>\n\u30e1\u30a4\u30f3\u30d7\u30ed\u30bb\u30b9\u5074\u306e\u51e6\u7406\u3092\u547c\u3073\u51fa\u3057\u3002<\/p>\n<div class=\"pre_tag\"><span><i class=\"fa fa-code\"><\/i> \u30ec\u30f3\u30c0\u30e9\u30fc\u30d7\u30ed\u30bb\u30b9 \u2013 index.js<\/span><\/p>\n<pre class=\"line-numbers\"><code class=\"language-js\">import { useState, useEffect } from \"react\";\n\nexport default function Home() {\n  \/\/ \u521d\u56de\u306e\u30a4\u30d9\u30f3\u30c8\n  useEffect(() =&gt; {\n    console.log(\"useEffect\");\n  }, []);\n\n  \/\/ \u30dc\u30bf\u30f3\u30a4\u30d9\u30f3\u30c8\n  const dialogAction = async (event) =&gt; {\n    console.log(\"dialogAction\");\n    await window.electron.dialogMsg(\"\u30c6\u30b9\u30c8\u3060\u3088\");\n  };\n\n  return (\n    &lt;div className=\"main\"&gt;\n      &lt;h1 id=\"test\"&gt;\n        \u53f3\u30af\u30ea\u30c3\u30af\u30b5\u30f3\u30d7\u30eb\n      &lt;\/h1&gt;\n\n      &lt;button id=\"test_button\" type=\"button\" onClick={dialogAction}&gt;\n        TEST\n      &lt;\/button&gt;\n\n      &lt;style jsx&gt;{`\n        h1 {\n          font-size: 20px;\n        }\n      `}&lt;\/style&gt;\n      &lt;style jsx global&gt;{`\n        body {\n          background-color: white;\n        }\n      `}&lt;\/style&gt;\n    &lt;\/div&gt;\n  );\n}\n\n<\/code><\/pre>\n<\/div>\n<p>\u7d50\u679c<br \/>\n<a href=\"https:\/\/www.oqiita.com\/wp-content\/uploads\/2021\/05\/002.gif\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2695\" src=\"https:\/\/www.oqiita.com\/wp-content\/uploads\/2021\/05\/002.gif\" alt=\"\" width=\"1370\" height=\"615\"><\/a><\/p>\n<h3 id=\"i-1\">h1\u30bf\u30b0\u3067\u53f3\u30af\u30ea\u30c3\u30af<\/h3>\n<p>\u307e\u3041\u30c0\u30a4\u30a2\u30ed\u30b0\u3068\u307b\u307c\u540c\u3058\u3067\u3059\u306d\u3002\u307e\u3041\u3042\u308c\u306a\u3093\u3067\u30ec\u30f3\u30c0\u30e9\u30fc\u306e\u307b\u3046\u306e\u30a4\u30d9\u30f3\u30c8\u3082\u30ad\u30c3\u30af\u3057\u307e\u3059\u3002<\/p>\n<p>\u307e\u305a\u306fpreload.js\u3092\u4fee\u6b63\u3002\u30ec\u30f3\u30c0\u30e9\u30fc \u2192 \u30e1\u30a4\u30f3\u306epopupMenu\u3092\u8ffd\u52a0\u3057\u3066\u3001\u30e1\u30a4\u30f3 \u2192 \u30ec\u30f3\u30c0\u30e9\u30fc\u3092\u8ffd\u52a0\u3057\u307e\u3057\u305f\u3002<\/p>\n<div class=\"pre_tag\"><span><i class=\"fa fa-code\"><\/i> preload.js<\/span><\/p>\n<pre class=\"line-numbers\"><code class=\"language-js\">const { ipcRenderer, contextBridge } = require(\"electron\");\ncontextBridge.exposeInMainWorld(\"electron\", {\n  \/\/ \u30ec\u30f3\u30c0\u30e9\u30fc \u2192 \u30e1\u30a4\u30f3\n  dialogMsg: async (data) =&gt; await ipcRenderer.invoke(\"dialogMsg\", data),\n  popupMenu: async (data) =&gt; await ipcRenderer.invoke(\"popupMenu\", data),\n  \/\/ \u30e1\u30a4\u30f3 \u2192 \u30ec\u30f3\u30c0\u30e9\u30fc\n  on: (channel, callback) =&gt;\n    ipcRenderer.on(channel, (event, argv) =&gt; callback(event, argv)),\n});<\/code><\/pre>\n<\/div>\n<p>\u6b21\u306b\u30e1\u30a4\u30f3\u30d7\u30ed\u30bb\u30b9\u5074\u3067\u30e1\u30cb\u30e5\u30fc\u4f5c\u6210\u3068\u305d\u308c\u3092\u8868\u793a\u3059\u308bipcMain\u3092\u8ffd\u52a0\u3002<\/p>\n<div class=\"pre_tag\"><span><i class=\"fa fa-code\"><\/i> \u30e1\u30a4\u30f3\u30d7\u30ed\u30bb\u30b9 \u2013 index.js<\/span><\/p>\n<pre class=\"line-numbers\"><code class=\"language-js\">\/\/ \u30e1\u30cb\u30e5\u30fc\u3092\u4f5c\u6210\nconst menu = Menu.buildFromTemplate([\n  {\n    label: \"Test Menu\",\n    click: () =&gt; {\n      \/\/ \u30a6\u30a3\u30f3\u30c9\u30a6\u3092\u53d6\u5f97\u3057\u3066\u3001\u30ec\u30f3\u30c0\u30e9\u30fc\u306b\u901a\u77e5\n      const w = BrowserWindow.getFocusedWindow();\n      w.webContents.send(\"popuo-return\");\n    },\n  },\n  { type: \"separator\" },\n  { role: \"quit\" },\n]);\n\/\/ \u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u30e1\u30cb\u30e5\u30fc\u3092\u8868\u793a\nipcMain.handle(\"popupMenu\", (event) =&gt; {\n  const w = BrowserWindow.getFocusedWindow();\n  menu.popup(w);\n  return;\n});<\/code><\/pre>\n<\/div>\n<p>\u30ec\u30f3\u30c0\u30e9\u30fc\u5074\u3067\u306fonContextMenu\u3092\u8ffd\u52a0\u3057\u3066contextMenu\u30a4\u30d9\u30f3\u30c8\u3092\u547c\u3073\u51fa\u3057\u3066\u3001ContextMenu\u3092\u8868\u793a\u3057\u3066\u3001<br \/>\n\u30e1\u30cb\u30e5\u30fc\u3092\u9078\u629e\u3057\u305f\u3089\u3001popuo-return\u3092\u8d77\u52d5\u3057\u3066\u3001\u30ec\u30f3\u30c0\u30e9\u30fc\u5074\u3067Alert\u3092\u8868\u793a\u3002<\/p>\n<div class=\"pre_tag\"><span><i class=\"fa fa-code\"><\/i> \u30ec\u30f3\u30c0\u30e9\u30fc\u30d7\u30ed\u30bb\u30b9 \u2013 index.js<\/span><\/p>\n<pre class=\"line-numbers\"><code class=\"language-js\">import { useState, useEffect } from \"react\";\n\nexport default function Home() {\n  \/\/ \u521d\u56de\u306e\u30a4\u30d9\u30f3\u30c8\n  useEffect(() =&gt; {\n    console.log(\"useEffect\");\n\n    window.electron.on(\"popuo-return\", (event) =&gt; {\n      alert(\"\u53f3\u30af\u30ea\u30c3\u30af\u304b\u3089\u306e\u30a2\u30e9\u30fc\u30c8\");\n    });\n  }, []);\n\n  \/\/ \u53f3\u30af\u30ea\u30c3\u30af\u30e1\u30cb\u30e5\u30fc\n  const contextMenu = async (event) =&gt; {\n    console.log(\"contextMenu\", event.currentTarget);\n    event.preventDefault();\n    await window.electron.popupMenu();\n  };\n\n  \/\/ \u30dc\u30bf\u30f3\u30a4\u30d9\u30f3\u30c8\n  const dialogAction = async (event) =&gt; {\n    console.log(\"dialogAction\");\n    await window.electron.dialogMsg(\"\u30c6\u30b9\u30c8\u3060\u3088\");\n  };\n\n  return (\n    &lt;div className=\"main\"&gt;\n      &lt;h1 id=\"test\" onContextMenu={contextMenu}&gt;\n        \u53f3\u30af\u30ea\u30c3\u30af\u30b5\u30f3\u30d7\u30eb\n      &lt;\/h1&gt;\n\n      &lt;button id=\"test_button\" type=\"button\" onClick={dialogAction}&gt;\n        TEST\n      &lt;\/button&gt;\n\n      &lt;style jsx&gt;{`\n        h1 {\n          font-size: 20px;\n        }\n      `}&lt;\/style&gt;\n      &lt;style jsx global&gt;{`\n        body {\n          background-color: white;\n        }\n      `}&lt;\/style&gt;\n    &lt;\/div&gt;\n  );\n}<\/code><\/pre>\n<\/div>\n<p>\u7d50\u679c<br \/>\n<a href=\"https:\/\/www.oqiita.com\/wp-content\/uploads\/2021\/05\/003.gif\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2696\" src=\"https:\/\/www.oqiita.com\/wp-content\/uploads\/2021\/05\/003.gif\" alt=\"\" width=\"1369\" height=\"614\"><\/a><\/p>\n<p>\u4ee5\u4e0a\u3067\u3059\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u7a81\u7136\u59cb\u3081\u305f\u304b\u3089\u521d\u5fc3\u8005\u30ec\u30d9\u30eb\u3084\u3067\u3002<\/p>\n","protected":false},"author":1,"featured_media":2699,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[297],"tags":[300,301,298,299],"class_list":{"0":"post-2685","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-electron","8":"tag-contextbridge","9":"tag-contextmenu","10":"tag-electron","11":"tag-next-js","12":"entry"},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/www.oqiita.com\/wp-content\/uploads\/2021\/05\/sango_electron_icatch.png","jetpack_shortlink":"https:\/\/wp.me\/p8QluP-Hj","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.oqiita.com\/index.php?rest_route=\/wp\/v2\/posts\/2685","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.oqiita.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.oqiita.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.oqiita.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.oqiita.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2685"}],"version-history":[{"count":18,"href":"https:\/\/www.oqiita.com\/index.php?rest_route=\/wp\/v2\/posts\/2685\/revisions"}],"predecessor-version":[{"id":2707,"href":"https:\/\/www.oqiita.com\/index.php?rest_route=\/wp\/v2\/posts\/2685\/revisions\/2707"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.oqiita.com\/index.php?rest_route=\/wp\/v2\/media\/2699"}],"wp:attachment":[{"href":"https:\/\/www.oqiita.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2685"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.oqiita.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2685"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.oqiita.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2685"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}