Author: Hongying Guo Editor: Xiaoli Tan

background

We developed a browser plug-in that usesXigua ~On behalf of, for the operation of students and other convenient view of the video of some data, the plug-in currently has a lot of repeated rendering problems, recently intends toXigua ~The project will conduct component rendering optimization. First, the React Devtools plug-in will be used for performance testing and code debugging of the current plug-in, so as to summarize the benefits before and after optimization. However, when you open the Components debugger, you will find that the Dom tree has only one root of the original page and cannot detect the plug-in’s Dom tree.

React Devtools icon

Blue: generation environment Red: Development environment Gray: non-React projects

Also, on the Watermelon PC station, the React Devtools icon is blue.

When on the Youtube page, the React Devtools icon is gray.

This shows that the React Devtools plugin does not detect the context of the plugin.

Why can’t you debug plug-ins?

Devtools plug-in apis

The Devtools plug-in operates on or listens for panels, censored Windows, and network requests through the following set of apis:

  • Chrome.devtools. panels: Panels related;
  • Chrome. Devtools. InspectedWindow: to get information about the window under review;
  • Chrome.devtools.network: Get information about web requests;

The React Devtools plug-in

The React Devtools plugin sets a global hook named __REACT_DEVTOOLS_GLOBAL_HOOK__ during page loading, and communicates with the plugin through this hook during React initialization.

The following source code, which detects that the current page type is HTML, inserts a script tag containing the code to initialize __REACT_DEVTOOLS_GLOBAL_HOOK__.

If ('text/ HTML '=== document.contentType) {injectCode(// injectCode is the logic that inserts script tags '; (' + installHook. ToString () + // installHook will set __REACT_DEVTOOLS_GLOBAL_HOOK__ '(window))' + saveNativeValues + detectReact, ); } Object.defineProperty( target, '__REACT_DEVTOOLS_GLOBAL_HOOK__', ({ configurable: __DEV__, enumerable: false, get() { return hook; }, }: Object), );Copy the code

The react function is checked by checking whether the __REACT_DEVTOOLS_GLOBAL_HOOK__ global variable exists and whether there is a render instance.

chrome.devtools.inspectedWindow.eval( 'window.__REACT_DEVTOOLS_GLOBAL_HOOK__ && window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers.size > 0', function(pageHasReact, error) { if (! pageHasReact || panelCreated) { return; }} / /... }Copy the code

As you can see from the above logic, Devtools always interacts with window, the current page namespace, and Devtools cannot communicate with the Buddy plug-in namespace.

As can be seen from the figure, Devtools can communicate with Inspected Window and Background Page, but cannot communicate with Content Script. This is why React Devtools doesn’t debug or perform performance checks on Buddy pages.

How to debug the Content Script plug-in?

  1. Using the developer tools Performance, React automatically reports the rendering time of each component in the development environment. This scheme is more suitable for the overall performance of the project, when the need for a specific component of the rendering detection is not very convenient.

2. Use React’s experimental API Profiler, as shown below, to test the rendering time of a component by using the Profiler component wrapped and defining the onRender callback function.

import React, { unstable_Profiler as Profiler } from 'react'; Export default function TestComp () {function onRenderCallback (id, "id" phase, // "mount" (if the component tree was just loaded) or "update" (if it rerenders) one actualDuration, // Set rendering time baseDuration, // Estimate the time required to render the entire subtree without memoization, startTime, commitTime, {console.log(' ${id} component render time: ', actualDuration); Console. log(' ${id} component does not use Memo to estimate render time: ', baseDuration); Return (<Profiler id="XgVideo" onRender={onRenderCallback}> <div> // component content </div> </Profiler>)}Copy the code

The result is shown below:

Profiler uses the Performance.measure() API to implement markup reporting. For example, we can also autonomously report information to developer tool Performance with the following code:

<! DOCTYPE html> <html> <head> <title></title> </head> <body> <script type="text/javascript"> Performance. Mark (" Test report performance-start "); // Wait some time. SetTimeout (function() {// Indicates the end of time. Performance. Mark (" Test report performance -end"); // Measure two different flags. Performance. Measure (" Test reports performance ", "test reports performance-start "," test reports performance-end "); // Clear the stored flag bit performance.clearmarks (); performance.clearMeasures(); }, 1000); </script> </body> </html>Copy the code

Added: Disable React Devtools from changing state and props

The React Devtools plugin can also be used to make changes to the props and props in the production environment, which may cause security problems. You can partially disable changes to the state and props in the build environment by running the following code before using React.

if (process.env.NODE_ENV == 'production' && typeof window.__REACT_DEVTOOLS_GLOBAL_HOOK__ === 'object') {
    __REACT_DEVTOOLS_GLOBAL_HOOK__.inject = function() {};
}
Copy the code

Refer to the link

  • Some data calculation statistical methods for Performance
  • Flag to disable devtools