top of page

head1

id

Table of contents

react-devtools-inline をアプリに入れ込んでHTMLElementからFiberを取得する

更新日:2022年8月8日



前回の記事の続きです。


React Developer Tools がどのようにソースコードを特定しているのかわかりました。

Fiberの中に情報が入っており、HTMLElementからFiberは取得できます。


ということは react-devtoolsのバックエンドが動いている場合に、HTMLElementからReactコンポーネントのソースコードがわかるということです。


なので、今回はReact Devtoolsを組み込める。

react-devtools-inline を使って任意のWebアプリのHTMLElementからFiberを取得することができるのかということをやっていきます。

 

というか react-devtools-inline のREADMEを読んで初期化しているがうまく動かない。なぜ?


window.__REACT_DEVTOOLS_GLOBAL_HOOK__ に値が入っているはずなのだが...


とりあえず、 スタンドアロン版 があるのでそれで進める。



 

なんとなくやりたいことができた。 ホバーしたコンポーネントのソース位置を表示して、VsCodeで開くことができる。



事前の準備としては、下記の2つが必要 ソースを調査したいアプリのルートで下記のコマンドでスタンドアロン版のReact dev toolsを起動しておく。


1

npx react-devtools

また、下記のコードをソースを調査したいアプリのHTMLで読み込んでおく。


2

const devToolsScript = document.createElement("script");
devToolsScript.setAttribute("src", "http://localhost:8097");
document.head.appendChild(devToolsScript);

const init = () => {
  let tmpBoder = "";
  window.addEventListener("pointerout", (e) => {
    if (!e.target || !window.__REACT_DEVTOOLS_GLOBAL_HOOK__) return;
    e.target.style.border = tmpBoder;
  });

  window.addEventListener("pointerover", (e) => {
    if (!e.target || !window.__REACT_DEVTOOLS_GLOBAL_HOOK__) return;

    const renderer = window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers.get(1);
    if (!renderer) return;

    tmpBoder = e.target.style.border;

    const fiber = renderer.findFiberByHostInstance(e.target);
    if (fiber && fiber._debugSource) {
      e.target.style.border = "1px solid blue";
    
      window.parent.postMessage(
        { source: "tailwind-editor", _debugSource: fiber._debugSource },
        "*"
      );
    }
  });
};

devToolsScript.addEventListener("load", init);

やっていることはホバーしている要素からFiberを取得できたらソースコードの情報をpostMessageを通じて親のWindowに通信している。


親のWindowはこの調査したいアプリをiframeとして読み込んでおり、ソースコードが送られてくるので、ツールチップで表示しているだけ。


最終的にはこれはVsCodeのエクステンションに送られる想定。


次は送られた値を使ってファイルを読み込みBabelで解析してclassNameを取得する処理を書く

bottom of page