Skip to content
This repository has been archived by the owner on Jul 30, 2018. It is now read-only.

Features & Brainstorming #4

Open
umaar opened this issue Jan 22, 2018 · 6 comments
Open

Features & Brainstorming #4

umaar opened this issue Jan 22, 2018 · 6 comments
Assignees

Comments

@umaar
Copy link
Member

umaar commented Jan 22, 2018

As per dojo/meta#227 - this GitHub issue presents the research made on a Dojo 2 DevTools extension.

This thread specifies the following:

  1. Task backlog: A list of potential tasks to do for a Dojo 2 DevTools extensions Features & Brainstorming #4 (comment)
  2. Dojo 2 DevTools learnings: A case study of how the current DevTools extension works Features & Brainstorming #4 (comment)
  3. Third party extensions: Learnings from some other JS framework DevTools extensions Features & Brainstorming #4 (comment)
@umaar umaar self-assigned this Jan 22, 2018
@umaar
Copy link
Member Author

umaar commented Jan 23, 2018

One of the goals of this issue is to come up with a backlog of tasks which could be done:

Things to watch out for

  • Try to avoid reinventing the wheel. If DevTools can already display, for example, logs (which it can), we can use that instead of building a custom 'event logger'
  • Make sure extension is fairly response/fluid (see Vue DevTools for an excellent example of this)
  • Explain + document what the extension is capable of in the extension web store so people know what to expect from it. Include screenshots

General

  • Are we starting from scratch? Or continuing with the extension part of this repo?
  • The user should not need to change their application source code in order to debug it
  • Setup the initial project structure/github repo (use this repo)
  • Chrome Extension on GitHub + Chrome Webstore + Documentation on webstore upload process
  • Basic level of branding would be nice: E.g. logos
  • Document how the extension is published
  • Ensure team are aware on how to build + publish the extension
  • Chrome Page Action to indicate when the current page can be inspected by Dojo DevTools
  • Inject JavaScript into the inspected page when the panel is open, the 'bootstrap' the page. This github project demonstrates it well.
  • Two way message passing solution, allowing the DevTools panel to communicate with the inspected page, and vice versa. This github project demonstrates it well.
  • Implement Dojo 2 detection mechanism, so that a browser extension can efficiently detect if Dojo 2 is being used on the current page
  • Implement a basic panel which displays helpful UI/UX when Dojo is a) detected but in an un-inspectable state (e.g. it's not in debug mode)
  • Implement a panel view which to explain when Dojo 2 cannot be detected in the current inspected page
  • Implement a panel view to show when Dojo has been detected and can be inspected
  • Ensure a refresh of the page also refreshes the DevTools extension
  • Do we want to support other debugging clients. We could support, for example, automation tooling to extract the same diagnostic and profiling messaging which the DevTools extension would normally pick up. Functional tests could hook into these and display output on test failures

Changes to Dojo core modules

  • The core Dojo modules need instrumenting + exposing certain data for visualisation in the DevTools, this needs to be figured out & explained (as GitHub issues in those projects)
  • Have the build system remove debugging code

Widget Tree + Properties Pane

  • Widget tree visuliser
  • Ensure the widget tree can be navigated using keyboard controls
  • Inspect specific widget(s) and see live events relating to it
  • Make the widget tree look more like the dev tools elements view (i.e. inline attribute/properties)
  • Updating properties via the widget tree that triggers a these to re-render
  • Update the widget tree when the live DOM is updated
  • Click through to functions on the widget (and map to source code)
  • Node tooltips to indicate where a node is and whether it is out of the viewport. Warning: The current implementation applies an outline around the element via a style attribute. We should fix this to use an overlay
  • When I click on a node, the outline should include the node's margins like Chrome's "Elements" pane does.
  • Provide a widget node context menu so that you can right click -> reveal in elements panel
  • We can show a custom sidebar (with the chrome.devtools.panels.elements.createSidebarPane API) in the Elements Panel so that when you inspect an element (in the built-in Elements Panel), a sidebar can show you extra properties on that element. This may be redundant with a Widget Inspector however, we should decide if it's worth doing.

Performance

  • Re-render highlighting

Stores

  • Implement an appropriate view for when stores is not present in the page
  • Stores visualiser
  • Time travel debugging
  • Live updating of properties

Event Log

  • Need to determine if an event log would be useful for users
  • Where should emitted events go? Debug logs = console panel
  • Performance timing logs = Performance Panel with performance.mark
  • Contextual info which requires the custom Dojo 2 panel to display can go into a __window.dojo_devtool_debug__ array which is collected by the extension and presented within the custom panel when the user opens it

@umaar
Copy link
Member Author

umaar commented Jan 23, 2018

How is the widget tree rendered?

In the interest of documentation and knolwedge sharing, here is my understanding of how the Widget tree (the Dojo 2 DevTools version of the Elements Panel) works end to end in the current implementation.

Warning: The current implementation requires the inspectable app to make source code changes, hopefully the knowledge here can take us on a clearer path to avoid having to do that.

Overview: The widget tree renders a visual tree-like overview of the rendered VDOM structure. There are three parts to making it work:

  • The user-facing part, the DevTools extension (which is a Dojo 2 app)
  • The debugging code, the diagnostics package
  • The communication channel, basically an eval() on the inspected page

It starts from this line of code which the DevTools extension invokes on the inspected page: window.__dojo2_diagnostics__.getProjectorLastRender('projector_1') so it can use the return data of that function to display the widget tree.

To make all of this work, the sample app must import the modified projector: import ProjectorMixin from '@dojo/diagnostics/wrappers/Projector';. The projector and the debuggable Dojo 2 app is used in the usual way, all that changes are the imports.

First, hooks are put into the code Projector code, these hooks hook into the original projector, the only difference is the hooks emit data about what is happening.

https://github.com/dojo/diagnostics/blob/66f5388b6030aebe242cc2f15664c8069546263c/src/wrappers/Projector.ts#L109-L118

The key part here is this._diagnosticRender. _diagnosticRender represents an object which has a rendered property, that rendered property is specified here https://github.com/dojo/widget-core/blob/56699f9128155c0b286ef0260667dffce55f3b50/src/vdom.ts#L706

The property value is an array of rendered nodes (nodes which were actually rendered into the DOM). Going back to the hooks, they emit events which are picked up by diagnostics e.g. diagnosticEvents.emit({type: 'projector:attach'}). This is listened for here: https://github.com/dojo/diagnostics/blob/master/src/diagnosticEvents.ts#L333 and it invokes the updateRender method upon event emission. It receives the result (rendered DOM nodes) and assigns it to lastRender: to a Map of projectors. That map is accessed here:

https://github.com/dojo/diagnostics/blob/23a01e0e49c61b60401d583d348547d9cd366ce9/src/main.ts#L99-L104

And is what makes __dojo2_diagnostics__.getProjectorLastRender('projector_1') work. (You can try it in the console panel). Notice, before the projector data is returned, it's serialized with this:

https://github.com/dojo/diagnostics/blob/23a01e0e49c61b60401d583d348547d9cd366ce9/src/serializeDNode.ts#L180-L184

This serialization process 'prepares' the rendered DOM into something which can be visually displayed. For example, instead of the object property widgetConstructor being represented by a function, it's converted to a string.

Now that we've seen how __dojo2_diagnostics__.getProjectorLastRender('projector_1') works, you might notice the return value of getProjectorLastRender provides everything needed to construct a VDom representation on the Dojo 2 DevTools panel.

Note: the remaining explanations from this point on applies to any Dojo 2 app which uses stores.

State management is set up in the usual way, and this property is exposed to the DevTool widget: interface: get(path('interface')). That interface property contains the value of: await getLastRender(selectedProjector) (shown here).

💡 Tip: getLastRender() eventually invokes window.__dojo2_diagnostics__.getProjectorLastRender('projector_1') which we saw earlier.

lastRender is assigned to root shown here at which point it is used as a child property to render the DevTools widget tree:

w(VDom, {
    root
});

That VDom widget contains a render implementation like this

protected render(): DNode {
if (this.properties.root && !this._root) {
this._root = this._mapNodes(this.properties.root);
}

and constructs the necessary widget tree you can see within the extension.

@umaar
Copy link
Member Author

umaar commented Jan 23, 2018

Learnings from other DevTools Extensions

React DevTools

webstore / source code

Details

  • 847,882 users on the Chrome Web Store, 4/5 star rating
  • Extension built-in react

Page Actions

While a DevTools extensions can only appear within the DevTools, it's possible to apply some behaviour to your the extension button next to the browser address bar.

image

The React DevTools highlights red when it detects the current webpage is using an inspectable version of React. The Dojo 2 DevTools extension can follow the same behaviour.

The main feature of the React DevTools is a component/widget/element inspector:

image

It closely resembles the native built-in DevTools element inspector. Features include:

  • Element highlight overlay so you can see which element is being inspected
  • Element dimensions highlight overlay so you can see the visual size for margin/padding etc.
  • Element tooltip which specifies: the pixel measurements of the element + the element name + where in the page viewport the element is. If the element is outside of the viewport, the tooltip indicates this.
  • Element context menu

image

  • The element context menu provides useful utilities which Dojo DevTool can implement too, such as: Copy element props which gives a JSON object in your clipboard containing all the properties of the inspected element.
  • The element context menu provides a 'Find node' item which takes you to the same node in the elements panel
  • The element context menu also provides a Show [component name] source which takes you to the Sources Panel where you can see the line of code which creates the inspected component (this feature wasn't working for me)
  • With the panel there is an option to Highlight updates

image

This option, when enabled, displays an outline around DOM elements which have updated/rendered during the page lifecycle. The Dojo team have expressed this is a useful feature.

  • The React DevTools includes a property inspector which contains information for the inspected element. You can also edit properties (property updates not currently working)

image

  • There is also an option to "Highlight search". When enabled, this feature visually highlights elements on the page which matches a search query you make:

image

  • Within the property inspector, you can copy property values to your clipboard, this includes functions:

image

This allows you to paste and execute the function into your console panel. The binding is maintained.

  • Within the property inspector, there is also the option to see a function source code (feature not working for me)

Vue DevTools

webstore / source code

Details

  • 363,908 users on the Chrome Web Store, 5/5 star rating
  • Extension built-in Vue

The Vue DevTools extension has a sensible interface and a good UX/DX. Large buttons with lots of spacing, it's all responsive too.

image

Similar to React, it uses page actions to inform you if the current page is inspectable:

image

  • Like React DevTools, the Vue DevTools has a similar Component/Widget inspector which displays the components and their properties. Properties are usually editable, however this feature wasn't working.
  • The ability to go from Vue Component Inspector -> Elements Panel is possible:

image

  • Both the property inspector and the component inspector have live updating filterable input boxes. As you type in, child items are matched against your query and filtered down.
  • There's an interesting 'open component in your editor' feature which allows you to go from Vue DevTools -> Code editor in a single click:

image

This feature requires code changes and is documented here

  • Vue DevTools hooks into the Chrome context menu:

image

So when you Right Click on a webpage, you have the option to inspect the Vue component with the Vue DevTools. This is done via the menus.create() API shown here

  • Aside from the component inspector, there is also an events panel within the Vue DevTools:

image

Couldn't get this feature to work.

More Vue DevTools features are shown here: https://medium.com/the-vue-point/whats-new-in-vue-devtools-4-0-9361e75e05d0

  • The Vue DevTools includes a VueX debugger. VueX is a centralized state management tool for Vue.
  • VueX debugging features includes the ability to import/export state objects in real time:

image

  • The VueX debugger also supports time travelling

image


Angular DevTools (Named AngularJS Batarang)

webstore / source code

Details

  • 273,125 users on the Chrome Web Store, 2.5/5 star rating

Angular DevTools had a slightly unintuitive interface + UX.

image

  • While having a basic UX, the DevTools did offer the usual customised element inspector + editable property inspector:

image

  • A built in 'hints' tab is present:

image

It provides, what appeared to be, best practice suggestions for application source code which uses Angular.

  • A performance tab is present:

image

It shows various lifecycle events with timing information.


Ember DevTools (Named Ember Inspector)

webstore / source code

Details

  • 65,565 users on the Chrome Web Store, 5/5 star rating

The Ember DevTools is very feature rich:

image

  • It includes a route inspector:

image

So you can see registered and active routes, but also the templates + controllers associated with routes.

  • There is an information pane which lists the version numbers of Ember & Ember Inspector
  • There is a promises inspector to list the fulfillment state of JavaScript promises in the application
  • There is a Render Performance pane:

image

It shows rendering events and their timing durations for the application.


Kuker DevTools

webstore / source code

Details

Kuker works differently, it is a single DevTools frontend for React, Angular, Vue & Vuex, Redux, redux-saga, HTML, Stent, Machina.js, MobX. It's still a Chrome Extension which is part of the DevTools, but it relies on certain application instrumentation

As there isn't really a unified way of building a widget/component inspector + corresponding properties pane, various framework developers tend to create their own DevTools, and this project seems help standardise on this.

@edhager
Copy link

edhager commented Jan 24, 2018

Kuker is really just a postMessage message viewer. It looks for the messages to have the property "kuker" set to true. It uses the "type" property on the messages for filtering and for a difference calculating feature.

If you install the Kuker extension, you can see it in action here.

I fear Kuker does not have the features we want. We are looking to help the user map the virtual DOM to the DOM and the themes to the actual CSS and right now, I don't see a way to make Kuker do those things.

Kuker has a nifty utility function. To use Kuker, your application has to act as what it calls an "emitter" to produce messages that the devtool can receive. In the kuker-emitters, there is a nifty utility function that makes it easy to create an emitter that will work in both a browser and in a Node.js application: https://github.com/krasimir/kuker-emitters/blob/master/src/helpers/createMessenger.js

@edhager
Copy link

edhager commented Jan 24, 2018

I like the idea of using postMessage as a marshalling mechanism between the devtool and the Dojo 2 web application. I'm not a fan of the way the current devtool uses exec to retrieve data from the web application. I would rather see the devtool send a message that says "give me this data" and then response to the "here is some data" message produced by the web application. I think that give us more flexibility to make changes down the road to both the diagnostics code and the devtool.

@krasimir
Copy link

krasimir commented Jan 25, 2018

I fear Kuker does not have the features we want. We are looking to help the user map the virtual DOM to the DOM and the themes to the actual CSS and right now, I don't see a way to make Kuker do those things.

That is something which is missing in the other frameworks integrations and it is added to my todo list. Probably will be standardized as a command from the extension to the page. The input of this command should be provided by the emitter in the form of a selector.

@edhager edhager mentioned this issue Jan 29, 2018
8 tasks
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants