UltramanWeiLai/react-dev-inspector
click react component then jump to component's source code in your local IDE.
React Dev Inspector
Introduction
This package allows users to jumping to local IDE code directly from browser React component by just a simple click, which is similar to Chrome inspector but more advanced.
Preview
online demo: https://react-dev-inspector.zthxxx.me
press toggle hotkey (
ctrl⌃ + shift⇧ + commmand⌘ + c) then move mouse and click to try it out.
screen record gif (8M size):
Installation
npm i -D react-dev-inspectorUsage
Users need to add React component and some other webpac config to perform 'react-dev-inspector' in your own projects.
Note: It should be limited to use this package in production mode, as the same as React component and webpack config
Use Inspector React Component
import React from 'react'
import { Inspector, InspectParams } from 'react-dev-inspector'
const InspectorWrapper = process.env.NODE_ENV === 'development'
? Inspector
: React.Fragment
export const Layout = () => {
// ...
return (
<InspectorWrapper
// props docs see:
// https://github.com/zthxxx/react-dev-inspector#inspector-component-props
keys={['control', 'shift', 'command', 'c']}
disableLaunchEditor={false}
onHoverElement={(params: InspectParams) => {}}
onClickElement={(params: InspectParams) => {}}
>
<YourComponent>
...
</YourComponent>
</InspectorWrapper>
)
}Set Webpack Config
raw webpack config
A typical raw webpack config is shown below.
In this config, we add:
- an "inspector-loader"
- a "DefinePlugin" to get current working directory
- a "devServer" api middleware to open IDE on when it be called
import { Configuration, DefinePlugin } from 'webpack'
import { createLaunchEditorMiddleware } from 'react-dev-inspector/plugins/webpack'
const config: Configuration = {
// ...
/**
* [compile time] for inject source code file info
*/
module: {
rules: [
{
enforce: 'pre',
test: /\.[jt]sx$/,
exclude: [
/node_modules/,
/file-you-want-exclude/,
],
use: [
{
loader: 'react-dev-inspector/plugins/webpack/inspector-loader',
options: [{
// loader options docs see:
// https://github.com/zthxxx/react-dev-inspector#inspector-loader-props
exclude: [
'xxx-file-will-be-exclude',
/regexp-to-match-file /,
],
babelPlugins: [],
babelOptions: {},
}],
},
],
},
],
},
/**
* [compile time] for inject current working directory which used in web page runtime
*/
plugins: [
new DefinePlugin({
'process.env.PWD': JSON.stringify(process.cwd()),
}),
],
/**
* [server side] webpack dev server side middleware for launch IDE app
*/
devServer: {
before: (app) => {
app.use(createLaunchEditorMiddleware())
},
},
}It seems like the webpack config is too 'complicated', thus some integrated plugins / helper is provided for quick trial if your project happen to use these utils / frameworks.
So here are some ways for alternative the raw webpack config listed below:
usage with webpack-chain
This is almost equivalent to raw webpack config above,
but it will NOT override devServer.before, just add middleware before origin devServer.before
import { inspectorChainWebpack } from 'react-dev-inspector/plugins/webpack'
webpackChainConfig = inspectorChainWebpack(webpackChainConfig, {
// loader options docs see:
// https://github.com/zthxxx/react-dev-inspector#inspector-loader-props
exclude: [],
babelPlugins: [],
babelOptions: {},
})usage with Umi3
This is also equivalent to usage with webpack-chain
Example .umirc.dev.ts:
// https://umijs.org/config/
import { defineConfig } from 'umi'
export default defineConfig({
plugins: [
'react-dev-inspector/plugins/umi/react-inspector',
],
inspectorConfig: {
// loader options docs see:
// https://github.com/zthxxx/react-dev-inspector#inspector-loader-props
exclude: [],
babelPlugins: [],
babelOptions: {},
},
})usage with Umi2
Example .umirc.dev.js:
import { inspectorChainWebpack } from 'react-dev-inspector/plugins/webpack'
export default {
// ...
chainWebpack(config) {
inspectorChainWebpack(config, {
// ... options
})
return config
},
/**
* And you need to set `false` to `dll` in `umi-plugin-react`,
* becase these is a umi2 bug that `dll` cannot work with `devServer.before`
*
* https://github.com/umijs/umi/issues/2599
* https://github.com/umijs/umi/issues/2161
*/
}Configuration
<Inspector> Component Props
typescript define you can see in react-dev-inspector/es/Inspector.d.ts
| Property | Description | Type | Default |
|---|---|---|---|
| keys | inspector toggle hotkeys supported keys see: https://github.com/jaywcjlove/hotkeys#supported-keys |
string[] |
['control', 'shift', 'command', 'c'] |
| disableLaunchEditor | whether disable click react component to open IDE for view component code (launchEditor by default only support be used with react-dev-inpector plugins in dev) |
boolean |
false |
| onHoverElement | triggered while inspector start and mouse hover in a HTMLElement | (params: InspectParams) => void |
- |
| onClickElement | triggered while inspector start and mouse click on a HTMLElement | (params: InspectParams) => void |
- |
// import type { InspectParams } from 'react-dev-inspector'
interface InspectParams {
/** hover / click event target dom element */
element: HTMLElement,
/** nearest named react component fiber for dom element */
fiber?: React.Fiber,
/** source file line / column / path info for react component */
codeInfo?: {
lineNumber: string,
columnNumber: string,
relativePath: string,
},
/** react component name for dom element */
name?: string,
}Inspector Loader Props
// import type { ParserPlugin, ParserOptions } from '@babel/parser'
// import type { InspectorConfig } from 'react-dev-inspector/plugins/webpack'
interface InspectorConfig {
/** patterns to exclude matched files */
exclude?: (string | RegExp)[],
/**
* add extra plugins for babel parser
* default is ['typescript', 'jsx', 'decorators-legacy', 'classProperties']
*/
babelPlugins?: ParserPlugin[],
/** extra babel parser options */
babelOptions?: ParserOptions,
}IDE / Editor config
This package uses react-dev-utils to launch your local IDE application, but, which one will be open?
In fact, it uses an environment variable named REACT_EDITOR to specify an IDE application, but if you do not set this variable, it will try to open a common IDE that you have open or installed once it is certified.
For example, if you want it always open VSCode when inspection clicked, set export REACT_EDITOR=code in your shell.
VSCode
-
install VSCode command line tools, see the official docs

-
set env to shell, like
.bashrcor.zshrcexport REACT_EDITOR=code
WebStorm
- just set env with an absolute path to shell, like
.bashrcor.zshrc(only MacOS)export REACT_EDITOR='/Applications/WebStorm.app/Contents/MacOS/webstorm'
OR
-
then set env to shell, like
.bashrcor.zshrcexport REACT_EDITOR=webstorm
Vim
Yes! you can also use vim if you want, just set env to shell
export REACT_EDITOR=vimExample Project Code
- create-react-app
- umi3
How It Works
-
Stage 1 - Compile Time
- [webpack loader] inject source file path/line/column to JSX data attributes props (use babel)
- [webpack plugin] inject PWD (current working directory) env define for runtime
-
Stage 2 - Web React Runtime
-
[React component]
InspectorComponent in react, for listen hotkeys, and request api to dev-server for open IDE.Specific, when you click a component DOM, the
Inspectorwill try to obtain its source file info (path/line/column) and PWD path (both injected in Stage 1), then request launch-editor api (in stage 3) with absolute file path.
-
-
Stage 3 - Dev-server Side
-
[middleware] setup
createLaunchEditorMiddlewarein webpack dev-server (or other dev-server), to open file in IDE according to the request params.Only need in development mode,and you want to open IDE when click a component element.
Not need in prod mode, or you just want inspect dom without open IDE (set
disableLaunchEditor={true}to Inspector component props)
-
Analysis of Theory
- [chinese] 🎉我点了页面上的元素,VSCode 乖乖打开了对应的组件?原理揭秘

