PageSourceSearch

https://www.electronjs.org/assets/js/da83da33.60de7eb7.js

js electronjs.org collected 2026-09-24 07:03:38 UTC 16,764 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkelectronjs=self.webpackChunkelectronjs||[]).push([["20907"],{2875(e,o,n){n.r(o),n.d(o,{metadata:()=>t,default:()=>p,frontMatter:()=>r,contentTitle:()=>a,toc:()=>c,assets:()=>d});var t=JSON.parse('{"id":"latest/tutorial/devtools-extension","title":"DevTools Extension","description":"Electron supports Chrome DevTools extensions, which can be used to extend the ability of Chrome\'s developer tools for debugging popular web frameworks.","source":"@site/docs/latest/tutorial/devtools-extension.md","sourceDirName":"latest/tutorial","slug":"/latest/tutorial/devtools-extension","permalink":"/docs/latest/tutorial/devtools-extension","draft":false,"unlisted":false,"editUrl":"https://github.com/electron/electron/edit/main/docs/tutorial/devtools-extension.md","tags":[],"version":"current","frontMatter":{"title":"DevTools Extension","description":"Electron supports Chrome DevTools extensions, which can be used to extend the ability of Chrome\'s developer tools for debugging popular web frameworks.","slug":"devtools-extension","hide_title":false},"sidebar":"docs","previous":{"title":"REPL","permalink":"/docs/latest/tutorial/repl"},"next":{"title":"Application Debugging","permalink":"/docs/latest/tutorial/application-debugging"}}'),s=n(74848),i=n(28453),l=n(40329);let r={title:"DevTools Extension",description:"Electron supports Chrome DevTools extensions, which can be used to extend the ability of Chrome's developer tools for debugging popular web frameworks.",slug:"devtools-extension",hide_title:!1},a="DevTools Extension",d={},c=[{value:"Loading a DevTools extension with tooling",id:"loading-a-devtools-extension-with-tooling",level:2},{value:"Manually loading a DevTools extension",id:"manually-loading-a-devtools-extension",level:2},{value:"Removing a DevTools extension",id:"removing-a-devtools-extension",level:3},{value:"DevTools extension support",id:"devtools-extension-support",level:2},{value:"What should I do if a DevTools extension is not working?",id:"what-should-i-do-if-a-devtools-extension-is-not-working",level:3}];function h(e){let o={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(o.header,{children:(0,s.jsx)(o.h1,{id:"devtools-extension",children:"DevTools Extension"})}),"\n",(0,s.jsxs)(o.p,{children:["Electron supports ",(0,s.jsx)(o.a,{href:"https://developer.chrome.com/docs/extensions/how-to/devtools/extend-devtools",children:"Chrome DevTools extensions"}),", which can\nbe used to extend the ability of Chrome's developer tools for debugging\npopular web frameworks."]}),"\n",(0,s.jsx)(o.h2,{id:"loading-a-devtools-extension-with-tooling",children:"Loading a DevTools extension with tooling"}),"\n",(0,s.jsxs)(o.p,{children:["The easiest way to load a DevTools extension is to use third-party tooling to automate the\nprocess for you. ",(0,s.jsx)(o.a,{href:"https://github.com/MarshallOfSound/electron-devtools-installer",children:"electron-devtools-installer"})," is a popular\nNPM package that does just that."]}),"\n",(0,s.jsx)(o.h2,{id:"manually-loading-a-devtools-extension",children:"Manually loading a DevTools extension"}),"\n",(0,s.jsxs)(o.p,{children:["If you don't want to use the tooling approach, you can also do all of the necessary\noperations by hand. To load an extension in Electron, you need to download it via Chrome,\nlocate its filesystem path, and then load it into your ",(0,s.jsx)(o.a,{href:"/docs/latest/api/session",children:"Session"})," by calling the\n",(0,s.jsx)(o.a,{href:"/docs/latest/api/extensions-api#extensionsloadextensionpath-options",children:(0,s.jsx)(o.code,{children:"ses.loadExtension"})})," API."]}),"\n",(0,s.jsxs)(o.p,{children:["Using the ",(0,s.jsx)(o.a,{href:"https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi",children:"React Developer Tools"})," as an example:"]}),"\n",(0,s.jsxs)(o.ol,{children:["\n",(0,s.jsxs)(o.li,{children:["\n",(0,s.jsx)(o.p,{children:"Install the extension in Google Chrome."}),"\n"]}),"\n",(0,s.jsxs)(o.li,{children:["\n",(0,s.jsxs)(o.p,{children:["Navigate to ",(0,s.jsx)(o.code,{children:"chrome://extensions"}),", and find its extension ID, which is a hash\nstring like ",(0,s.jsx)(o.code,{children:"fmkadmapgofadopljbjfkapdkoienihi"}),"."]}),"\n"]}),"\n",(0,s.jsxs)(o.li,{children:["\n",(0,s.jsx)(o.p,{children:"Find out the filesystem location used by Chrome for storing extensions:"}),"\n",(0,s.jsxs)(o.ul,{children:["\n",(0,s.jsxs)(o.li,{children:["on Windows it is ",(0,s.jsx)(o.code,{children:"%LOCALAPPDATA%\\Google\\Chrome\\User Data\\Default\\Extensions"}),";"]}),"\n",(0,s.jsxs)(o.li,{children:["on Linux it could be:","\n",(0,s.jsxs)(o.ul,{children:["\n",(0,s.jsx)(o.li,{children:(0,s.jsx)(o.code,{children:"~/.config/google-chrome/Default/Extensions/"})}),"\n",(0,s.jsx)(o.li,{children:(0,s.jsx)(o.code,{children:"~/.config/google-chrome-beta/Default/Extensions/"})}),"\n",(0,s.jsx)(o.li,{children:(0,s.jsx)(o.code,{children:"~/.config/google-chrome-canary/Default/Extensions/"})}),"\n",(0,s.jsx)(o.li,{children:(0,s.jsx)(o.code,{children:"~/.config/chromium/Default/Extensions/"})}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(o.li,{children:["on macOS it is ",(0,s.jsx)(o.code,{children:"~/Library/Application Support/Google/Chrome/Default/Extensions"}),"."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(o.li,{children:["\n",(0,s.jsxs)(o.p,{children:["Pass the location of the extension to the ",(0,s.jsx)(o.a,{href:"/docs/latest/api/extensions-api#extensionsloadextensionpath-options",children:(0,s.jsx)(o.code,{children:"ses.loadExtension"})}),"\nAPI. For React Developer Tools ",(0,s.jsx)(o.code,{children:"v4.9.0"}),", it looks something like:"]}
1),"\n",(0,s.jsx)(o.pre,{children:(0,s.jsx)(o.code,{className:"language-js",children:"const { app, session } = require('electron')\n\nconst os = require('node:os')\nconst path = require('node:path')\n\n// on macOS\nconst reactDevToolsPath = path.join(\n  os.homedir(),\n  '/Library/Application Support/Google/Chrome/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/4.9.0_0'\n)\n\napp.whenReady().then(async () => {\n  await session.defaultSession.loadExtension(reactDevToolsPath)\n})\n"})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(o.p,{children:(0,s.jsx)(o.strong,{children:"Notes:"})}),"\n",(0,s.jsxs)(o.ul,{children:["\n",(0,s.jsxs)(o.li,{children:[(0,s.jsx)(o.code,{children:"loadExtension"})," returns a Promise with an ",(0,s.jsx)(l.A,{url:"/docs/latest/api/structures/extension",title:"Extension object",content:'{"type":"root","children":[{"type":"element","tagName":"h1","properties":{},"children":[{"type":"text","value":"Extension Object"}]},{"type":"text","value":"\\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"id","position":{"start":{"line":10,"column":3,"offset":107},"end":{"line":10,"column":7,"offset":111}}}],"position":{"start":{"line":10,"column":3,"offset":107},"end":{"line":10,"column":7,"offset":111}}},{"type":"text","value":" string","position":{"start":{"line":10,"column":7,"offset":111},"end":{"line":10,"column":14,"offset":118}}}],"position":{"start":{"line":10,"column":1,"offset":105},"end":{"line":10,"column":14,"offset":118}}},{"type":"text","value":"\\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"manifest","position":{"start":{"line":11,"column":3,"offset":121},"end":{"line":11,"column":13,"offset":131}}}],"position":{"start":{"line":11,"column":3,"offset":121},"end":{"line":11,"column":13,"offset":131}}},{"type":"text","value":" any - Copy of the ","position":{"start":{"line":11,"column":13,"offset":131},"end":{"line":11,"column":32,"offset":150}}},{"type":"element","tagName":"a","properties":{"href":"https://developer.chrome.com/extensions/manifest"},"children":[{"type":"text","value":"extension\'s manifest data","position":{"start":{"line":11,"column":33,"offset":151},"end":{"line":11,"column":58,"offset":176}}}],"position":{"start":{"line":11,"column":32,"offset":150},"end":{"line":11,"column":109,"offset":227}}},{"type":"text","value":".","position":{"start":{"line":11,"column":109,"offset":227},"end":{"line":11,"column":110,"offset":228}}}],"position":{"start":{"line":11,"column":1,"offset":119},"end":{"line":11,"column":110,"offset":228}}},{"type":"text","value":"\\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"name","position":{"start":{"line":12,"column":3,"offset":231},"end":{"line":12,"column":9,"offset":237}}}],"position":{"start":{"line":12,"column":3,"offset":231},"end":{"line":12,"column":9,"offset":237}}},{"type":"text","value":" string","position":{"start":{"line":12,"column":9,"offset":237},"end":{"line":12,"column":16,"offset":244}}}],"position":{"start":{"line":12,"column":1,"offset":229},"end":{"line":12,"column":16,"offset":244}}},{"type":"text","value":"\\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"path","position":{"start":{"line":13,"column":3,"offset":247},"end":{"line":13,"column":9,"offset":253}}}],"position":{"start":{"line":13,"column":3,"offset":247},"end":{"line":13,"column":9,"offset":253}}},{"type":"text","value":" string - The extension\'s file path.","position":{"start":{"line":13,"column":9,"offset":253},"end":{"line":13,"column":45,"offset":289}}}],"position":{"start":{"line":13,"column":1,"offset":245},"end":{"line":13,"column":45,"offset":289}}},{"type":"text","value":"\\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"version","position":{"start":{"line":14,"column":3,"offset":292},"end":{"line":14,"column":12,"offset":301}}}],"position":{"start":{"line":14,"column":3,"offset":292},"end":{"line":14,"column":12,"offset":301}}},{"type":"text","value":" string","position":{"start":{"line":14,"column":12,"offset":301},"end":{"line":14,"column":19,"offset":308}}}],"position":{"start":{"line":14,"column":1,"offset":290},"end":{"line":14,"column":19,"offset":308}}},{"type":"text","value":"\\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"url","position":{"start":{"line":15,"column":3,"offset":311},"end":{"line":15,"column":8,"offset":316}}}],"position":{"start":{"line":15,"column":3,"offset":311},"end":{"line":15,"column":8,"offset":316}}},{"type":"text","value":" string - The extension\'s ","position":{"start":{"line":15,"column":8,"offset":316},"end":{"line":15,"column":34,"offset":342}}},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"chrome-extension://","position":{"start":{"line":15,"column":34,"offset":342},"end":{"line":15,"column":55,"offset":363}}}],"position":{"start":{"line":15,"column":34,"offset":342},"end":{"line":15,"column":55,"offset":363}}},{"type":"text","value":" URL.","position":{"start":{"line":15,"column":55,"offset":363},"end":{"line":15,"column":60,"offset":368}}}],"position":{"start":{"line":15,"column":1,"offset":309},"end":{"line":15,"column":60,"offset":368}}},{"type":"text","value":"\\n"}],"position":{"start":{"line":10,"column":1,"offset":105},"end":{"line":15,"column":60,"offset":368}}}],"position":{"start":{"line":1,"column":1,"offset":0},"end":{"line":16,"column":1,"offset":369}}}'}),",\nwhich contains metadata about the extension that was loaded. This promise needs to\nresolve (e.g. with an ",(0,s.jsx)(o.code,{children:"await"})," expression) before loading a page. Otherwise, the\nextension won't be guaranteed to load."]}),"\n",(0,s.jsxs)(o.li,{children:[(0,s.jsx)(o.code,{children:"loadExtension"})," cannot be called before the ",(0,s.jsx)(o.code,{children:"ready"})," event of the ",(0,s.jsx)(o.code,{children:"app"})," module\nis emitted, nor can it be called on in-memory (non-persistent) sessions."]}),"\n",(0,s.jsxs)(o.li,{children:[(0,s.jsx)(o.code,{children:"loadExtension"})," must be called on every boot of your app if you want the\nextension to be loaded."]}),"\n"]}),"\n",(0,s.jsx)(o.h3,{id:"removing-a-devtools-extension",children:"Removing a DevTools extension"}),"\n",(0,s.jsxs)(o.p,{children:["You can pass the extension's ID to the ",(0,s.jsx)(o.a,{href:"/docs/latest/api/extensions-api#extensionsremoveextensionextensionid",children:(0,s.jsx)(o.code,{children:"ses.removeExtension"})})," API to\nremove it from your Session. Loaded extensions are not persisted between\napp launches."]}),"\n",(0,s.jsx)(o.h2,{id:"devtools-extension-support",children:"DevTools extension support"}),"\n",(0,s.jsxs)(o.p,{children:["Electron only supports\n",(0,s.jsxs)(o.a,{href:"/docs/latest/api/extensions",children:["a limited set of ",(0,s.jsx)(o.code,{children:"chrome.*"})," APIs"]}),",\nso extensions using unsupported ",(0,s.jsx)(o.code,{children:"chrome.*"})," APIs under the hood may not work."]}),"\n",(0,s.jsx)(o.p,{children:"The following Devtools extensions have been tested to work in Electron:"}),"\n",(0,s.jsxs)(o.ul,{children:["\n",(0,s.jsx)(o.li,{children:(0,s.jsx)(o.a,{href:"https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi",children:"Ember Inspector"})}),"\n",(0,s.jsx)(o.li,{children:(0,s.jsx)(o.a,{href:"https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi",children:"React Developer Tools"})}),"\n",(0,s.jsx)(o.li,{children:(0,s.jsx)(o.a,{href:"https://chrome.google.com/webstore/detail/backbone-debugger/bhljhndlimiafopmmhjlgfpnnchjjbhd",children:"Backbone Debugger"})}),"\n",(0,s.jsx)(o.li,{children:(0,s.jsx)(o.a,{href:"https://chrome.google.com/webstore/detail/jquery-debugger/dbhhnnnpaeobfddmlalhnehgclcmjimi",children:"jQuery Debugger"})}),"\n",(0,s.jsx)(o.li,{children:(0,s.jsx)(o.a,{href:"https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd",children:"Vue.js devtools"})}),"\n",(0,s.jsx)(o.li,{children:(0,s.jsx)(o.a,{href:"https://cerebraljs.com/docs/introduction/devtools.html",children:"Cerebral Debugger"})}),"\n",(0,s.jsx)(o.li,{children:(0,s.jsx)(o.a,{href:"https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd",children:"Redux DevTools Extension"})}),"\n",(0,s.jsx)(o.li,{children:(0,s.jsx)(o.a,{href:"https://chrome.google.com/webstore/detail/mobx-developer-tools/pfgnfdagidkfgccljigdamigbcnndkod",children:"MobX Developer Tools"})}),"\n"]}),"\n",(0,s.jsx)(o.h3,{id:"what-should-i-do-if-a-devtools-extension-is-not-working",children:"What should I do if a DevTools extension is not working?"}),"\n",(0,s.jsx)(o.p,{children:"First, please make sure the extension is still being maintained and is compatible\nwith the latest version of Google Chrome. We cannot provide additional support for\nunsupported extensions."}),"\n",(0,s.jsxs)(o.p,{children:["If the extension works on Chrome but not on Electron, file a bug in Electron's\n",(0,s.jsx)(o.a,{href:"https://github.com/electron/electron/issues",children:"issue tracker"})," and describe which part\nof the extension is not working as expected."]})]})}function p(e={}){let{wrapper:o}={...(0,i.R)(),...e.components};return o?(0,s.jsx)(o,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},40329(e,o,n){n.d(o,{A:()=>c});var t=n(74848),s=n(20053),i=n(96540),l=n(75392),r=n.n(l),a=n(83561);let d=e=>(0,t.jsx)("article",{ref:e.innerRef,id:"structures-tooltip",role:"tooltip",className:(0,s.A)("alert","alert--info","shadow--md","card_ZoSr"),style:e.position,children:(0,t.jsx)("div",{className:"card__body",dangerouslySetInnerHTML:{__html:(0,a.V)(JSON.parse(e.content))}})}),c=function(e){let{Portal:o}=r()(),n=(0,i.useRef)(null),s=(0,i.useRef)(null),[l,a]=(0,i.useState)(!1),[c,h]=(0,i.useState)(void 0);(0,i.useEffect)(()=>
1{if(l){let e={x:0,y:0},o=n.current.getBoundingClientRect(),t=window.innerHeight/2<o.y,i=window.innerWidth/2<o.x;t?e.y=s.current.clientHeight+-2:e.y=-o.height- -2,i?e.x=s.current.clientWidth:e.x=0,h({top:n.current.offsetTop-e.y,left:n.current.offsetLeft-e.x})}},[l]);let p=(0,i.useCallback)(()=>{a(!0)},[]),u=(0,i.useCallback)(()=>{a(!1)},[]);return(0,t.jsxs)("a",{"aria-describedby":"structures-tooltip",href:e.url,ref:n,className:"link_nCrB",onMouseEnter:p,onMouseLeave:u,children:[e.title,!!l&&(0,t.jsx)(o,{children:(0,t.jsx)(d,{innerRef:s,position:c,...e})})]})}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.