vuejs / devtools-v6

⚙️ Browser devtools extension for debugging Vue.js applications.
https://devtools-v6.vuejs.org/
MIT License
24.63k stars 4.15k forks source link

Add standalone (electron) shell #451

Closed rigor789 closed 6 years ago

rigor789 commented 6 years ago

Vue-Devtools is an essential piece of the Vue ecosystem, but it is currently tied to a web browser.

It would be really nice if we had a tiny electron shell that can run the devtools without a browser, with the ability to remotely debug Vue apps.

For example, I would love to bring Vue devtools to nativescript-vue.

I'm not very familiar with the codebase, but as far as I can tell we could add a new shell, which would start an electron app, and a websocket server. The websocket server would be the bridge, and it would require a separate package to serve as the client.

(Side note: I found it a little confusing that the "client" side is called a backend, but that might be due to a different mindset.)

If someone more familiar with devtools wants to chat and get this going, I'm available!

michalsnik commented 6 years ago

Hey @rigor789 Thanks for posting this proposal and first PR. Also sorry for such a long response time...

But I'm happy to say we'd love to push this forward 🚀 As you can see there were lots of different issues that might be solved with this implementation. We finally cleared all of them and wish we can continue discussion in just one place - here.

I think what we'd like to achieve is exactly what you propose: standalone package with vue-devtools in electron, that communicates with browser over websockets. In order to inspect given page user should inject additional script (served from localhost, were our devtools console is running). It could probably still land in shells, and what I mean by standalone package is that it would have it's own package.json and would be released separately to npm.

React has exactly something like that already: https://github.com/facebook/react-devtools/tree/master/packages/react-devtools

They even separated it from shells and added it to dedicated packages

michalsnik commented 6 years ago

Let me know if you're still up for it. I'm happy to help :)

rigor789 commented 6 years ago

Hey @michalsnik, don't worry about the response time! :)

I'm up for working on this, although my schedule is a little busy for January I can squeeze in some time here and there to get this going.

I had a similar idea for having a separate package published to npm that would have to be used in the client code.

There was one idea that popped into my head recently, could we allow remote debugging in the browser shell too?

This would require making the Vue tab appear in devtools regardless of it being detected on the current page, a nice UI to let the user know that there was no Vue detected on the page, and perhaps a button for connecting to a remote page/app/anything. I haven't looked into the details, but I think this could work as long as the remote target is the host for the websocket server (or can a extension host a websocket server?).

Anyways, that's not too important, but worth looking into I guess.

Back to the electron shell,

I need to get familiar with the codebase again, but if you can summarize how this connection should work, that would be helpful.

What i'm thinking is when the electron app is launched, we launch a socket server as well, we can print the address of the server in the console, but It would be nice to add it to the UI as well.

Then we create a separate package that would essentially be a Vue plugin, so we can Vue.use it, which would then try to connect to the socket.

This is where things get tricky, how do we hook into Vue to trigger events / the transmission of the data to the socket server?

Potential issues:

Akryum commented 6 years ago

what if there are multiple clients?

We could have a tabbed interface with the url or title of each page.

michalsnik commented 6 years ago

I am also getting familiar with the codebase now @rigor789 and will try to hack it on my machine a bit to see what's possible and what's not :)

In terms of the work needed to be done I always say done is better than perfect. Let's not try to save the whole world in one day. Let's focus on what we do want to achieve in first version. Thats is:

Those 3 things are the bare minimum we have to implement. Once we have it we can realease beta. And then we can start thinking about multiple clients, different sockets and scenarios :)

michalsnik commented 6 years ago

I just implemented simple server thats runs alongside electron, handles websockets and serves updated backend.js to browser. I'm implementing bridge now. If it works I'll push to your branch working MVP @rigor789 This is fun!

rigor789 commented 6 years ago

Cool! I'll check it out when you push it.

And I fully agree about the MVP, let's focus on the basics first.

michalsnik commented 6 years ago

Implementation on this branch: https://github.com/vuejs/vue-devtools/tree/add-remote-devtools basically resolves first 3 parts I mentioned :) It turned out pretty easy.

Update: I pushed my changes to your fork too.

There was one idea that popped into my head recently, could we allow remote debugging in the browser shell too? I guess you mean we should show vue devtools tab even in remote chrome devtools? If yes - it's not possible. Extensions can't access this place. So we can only stick to our remote devtools instead, and leave browser extension as is :)

What i'm thinking is when the electron app is launched, we launch a socket server as well, we can print the address of the server in the console, but It would be nice to add it to the UI as well. It's the next step and to be honest I just started working on it. Sorry :3 This is too much fun!

Then we create a separate package that would essentially be a Vue plugin, so we can Vue.use it, which would then try to connect to the socket. Hmm.. for now let's stay with injecting script by hand. But in the end it might be a good idea. Though adding it on a page could also be as simple as:


import devTools from 'vue-devtools'

if (process.env.NODE_ENV !== 'production') { devTools.connect(); }


So I'm not sure we need a plugin for this, information in README should be enough.

> This is where things get tricky, how do we hook into Vue to trigger events / the transmission of the data to the socket server?
This is already solved, and ready on my branch. Communication was already well prepared by guys, and we only needed to add websockets bridge.

And about potential issues, now we can start thinking about them. The main for starters.

I see the following roadmap:
- [x] Add loading information, before application connects to electron server
- [x] Add README and update main README
- [ ] ~~Update development scripts so it's easier to jump right in and have at least on-save reload of remote devtools and background server~~
- [x] Add script for building app before release (we should publish package with `build`, but in git keep only `src` as is.
- [x] Add support for direct imports, instead of injecting script in HEAD
- [x] Handle multiple clients
- [ ] Handle potential connection problems
- [x] Suppress console logs in user browser

Once above things are ready - we can think about nativescript websockets issue. I didn't do anything in nativescript yet, so I might need some time to get my head around it.
michalsnik commented 6 years ago

Just for the record:

Update development scripts so it's easier to jump right in and have at least on-save reload of remote devtools and background server I was trying to come up with something but in the end I think actual implementation with proper README should be good enough.

michalsnik commented 6 years ago

Now it should be possible to either include script on the page, or just:

import devtools from 'vue-remote-devtools'
devtools.connect()
rigor789 commented 6 years ago

Looking good, I got it somewhat running locally, it connects, and detects the vue version, but I don't see any instances. my first thought was that the browser devtool was conflicting (it did get the correct data), so I disabled it, but then I got the issue that Cannot read property 'Vue' of undefined which is because window.__VUE_DEVTOOLS_GLOBAL_HOOK__ is not defined.

michalsnik commented 6 years ago

It shouldn't conflict with installed devtools extension, as I'm checking if there is already window.__VUE_DEVTOOLS_GLOBAL_HOOK__. What do you mean by instances? What do you see in electron app after refreshing your application?

michalsnik commented 6 years ago

I'll check however what's going on with this hook, when no vue devtools is preinstalled in browser.

michalsnik commented 6 years ago

We have to put hook init above all backend related code. It has to execute before backend code even loaded. I think I also see the first problem you mention, is it while using import instead of injecting <script> tag on page?

rigor789 commented 6 years ago

I only tried the <script> version, and it was at the top of the html file I was testing with.

By instances I mean root Vue instances, in the electron app I saw the initial screen with the text boxes, and when I refreshed my page, it changed to the devtools view, the Vue version was detected, but there was nothing in the inspector tree.

In the console, I saw messages about serializing instances, and the time it took in ms but it always said 0 instances

michalsnik commented 6 years ago

This worked for me when devtools extension was installed:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>auth-example</title>
    <script src="http://localhost:8098"></script>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

I'll look into in the evening :) We need to change few things

michalsnik commented 6 years ago

I just made it working without preinstalled extension. Should work both with injected script and import. "It works on my machine" :D Please let me know if you're still experiencing same issue @rigor789

rigor789 commented 6 years ago

Awesome, I'll check it out tomorrow, been a little busy...

rigor789 commented 6 years ago

Hey @michalsnik I said I would take a look but I didn't get a chance yet... Will try tomorrow if all goes to plan!

michalsnik commented 6 years ago

Sure, I think I just finished the initial version. Together with connection errors, handling multiple connection requests and so on. In order get as close to what people might experience after installing it you should do:

cd shells/electron && npm install && npm link

then just run:

vue-devtools

And follow instructions in Readme :) Hopefully it's gonna work for you seamlessly 🤞 Let me know, once you give it a shot!

rigor789 commented 6 years ago

Just tried it and it works great! A couple small things:

I've added a check for window.__VUE_DEVTOOLS_HOST__, and default to localhost

Edit:

I can remotely debug a page from a different machine, but for some reason I couldn't get it to work on my phone. Devtools successfully connects, I see the toast, the devtool window detects vue and everything but the component tree stays empty.

Further testing:

There are no errors in console, it connects fine but it says:

[flush] serialized 0 instances, took 0.26499999999998636ms.

Instead of

[flush] serialized 1 instances, took 0.6999999999999886ms.
michalsnik commented 6 years ago

Thanks @rigor789 I'll also do extensive testing and further integration with mobile devices hopefully today :) I noticed one thing that needs to be improved. Also for default host we should probably use 0.0.0.0 so it's accessible in LAN out of the box.

rigor789 commented 6 years ago

Is there anything that I should/can do?

michalsnik commented 6 years ago

I'm pushing few more changes and readme update. It will be also possible to set host like this from now on:

devtools.connect('192.168.1.12')

I just tested realworld-vue on few devices: Pixel - Chrome, Firefox Nexus 6 - Chrome Samsung Galaxy S5 - Chrome Iphone 10 - Safari Iphone 7 - Safari, Chrome, Firefox

And devtools worked fine. The only ones that it didn't work on was IOS <= 9 (probably because of ES6) if we transpile it to ES5 - it should probably work. Also UC Browser didn't seem to get it - probably same issue. I'll investigate it during this weekend and will provide a full list of supported systems and browsers.

I also experienced the issue you were talking about, with not all info sent to devtools. I found that in order to make them work correctly you have to put import devtools from '@vue/devtools' above Vue import. Try if this works for you :)

I'm also going to create a list of features not supported in this version of devtools (like for example selecting component on page). Then we'll think what to do about them.

michalsnik commented 6 years ago

If you'd like to investigate it however, feel free @rigor789 :)

michalsnik commented 6 years ago

Updated readme: https://github.com/rigor789/vue-devtools/blob/51ef52a8b7faf815af36ebc6b444336a3fbbe1b3/shells/electron/README.md

rigor789 commented 6 years ago

Very nice! I'll see if it works in nativescript (probably won't because I need to use native sockets)

michalsnik commented 6 years ago

The initial version doesn't have to work with nativescript. Let's review it and if it's fine we can release initial version and add native script support separately :) If you're looking at this topic - that's awesome @rigor789 !

rigor789 commented 6 years ago

Yep let's go for a release, we can worry about improvements later!

Akryum commented 6 years ago

I'll review it asap :smile:

TristanPct commented 6 years ago

Hi, thanks for this remote debugger. I'm trying to use it with a cordova app using global package but I have an error with socket.io: GET http://file/socket.io/?EIO=3&transport=polling&t=M7Rrv8y net::ERR_NAME_NOT_RESOLVED

The remote debugger works fine if I run my www folder on my computer (but not with my tablet).

Akryum commented 6 years ago

Now that we released the app, let's close this issue. If anyone has an problem with it, please open a new issue.