inject react code with console

196 阅读1分钟

记录一下研究了一半天的 react code inject,主要思路是使用 js inject 一段 html,并引入 react,babel 相关的 umd 库,然后使用 babel.transform + eval 进行渲染。

const $section = document.createElement('section');
$section.innerHTML = `
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="rootxxx"></div>
  </body>
  <script type="text/babel" name="qwe">
  const { useState } = React;

  const App = () => {
    const [a, setA] = useState(0);
    const onClick = () => setA((x) => x + 1);

    return (
      <div>
        hello, world! {a}
        <button onClick={onClick}>click me!</button>
      </div>
    );
  };
  ReactDOM.render(React.createElement(App), document.getElementById('rootxxx'));
  </script>
</html>
`;

$section.style.width = '100%';
$section.style.height = '800px';
$section.style.top = '0';
$section.style.left = '0';
$section.style.position = 'relative';
$section.style.zIndex = '9999';
$section.style.backgroundColor = 'white';
document.body.appendChild($section);

function loadScript(url) {
  return new Promise((res) => {
    const s = document.createElement('script');
    s.src = url;
    s.addEventListener('load', () => res(s));
    document.body.appendChild(s);
  });
}

loadScript('https://unpkg.com/react@17/umd/react.production.min.js')
  .then(() =>
    loadScript('https://unpkg.com/react-dom@17/umd/react-dom.production.min.js')
  )
  .then(() =>
    loadScript('https://unpkg.com/@babel/standalone@7.13.15/babel.js')
  )
  .then(() => {
    const scripts = document.querySelector('script[name="qwe"]');
    const { code } = Babel.transform(scripts.innerText, { presets: ['react'] });
    eval(code);
    alert('inject ok, scroll end to get it');
  });