We recently launched a new Replit-native way to inspect and debug web pages you build on Replit. Whether you're learning the basics or hosting a rich application, quickly being able to inspect the console and DOM is critical to your workflow.
Browsers ship with developer tools (e.g. Chrome), but they have a few shortcomings when working on Replit:
- Inspecting the nested webview iframe using browser DevTools can be complicated
- There are no solid solutions for developers working on mobile devices
- Some schools block access to browser DevTools
Now all repls that show a webview have access to a Replit-native set of DevTools. Just click the wrench icon to bring it up:
You can access the console:
Or inspect the DOM:
How we built it: Eruda
Eruda was a no brainer decision for us.
Challenges: permissions, security, and timing
The nature of a DevTool requires us to have underlying access to the DOM, the
window object, cookies, and other resources that are only available if we comply with the same origin policy. If you inspect the page, you'll notice we host devtools with the same origin as the repl itself within a magic
__devtools_wrapper.html file. All Repls have this hidden file that serves as a wrapper page for business logic related to the DevTool, including its injection and toggling.
console before our tools load.
Our first attempt looked roughly like this:
<iframe src="/"></iframe> <script src="devtools.js"></script>
By the time the devtools script kicks in, the iframe could have run some of its scripts. So we were missing some of the action.
Attempt two looked like this:
<iframe id="iframe"></iframe> <script> iframe.src = "/"; // modify iframe here </script>
The reference of
iframe.contentWindow will change after
src changes, and there is no way to know precisely when that happens. Modifying the
contentWindow at the wrong moment means we will be working with a disposed (and hence useless)
So we came up with attempt number three: we load an
src, then run.
const res = await fetch("/"); const html = await res.text(); injectDevTools(html); iframe.contentDocument.open(); iframe.contentDocument.write(html); iframe.contentDocument.close();
This works pretty well for the initial page, but the DevTools disappear when the user navigates to another page. To fix this, we listen to the
unload event and run the logic above again for any navigation. The last bug we had is that
location.reload within the iframe breaks since the
iframe technically has no
src, which was then fixed by adding a
history.pushState call on top.
Try it out!
We hope you like the new Replit-native DevTools. We're really enjoying the experience when working in the webview, either on desktop or mobile.
And if you enjoy hacking on frontend infrastructure (or other things...), consider joining us!