You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React-py应用中Python代码编辑器加载缓慢问题求助

问题:Next.js + react-py 代码编辑器渲染不稳定

我用Next.js和react-py开发了一款教育类应用,核心是让用户分块学习理论知识,同时在对应代码单元格里运行Python代码巩固练习。应用完全基于客户端运行,没有服务器端支持。目前遇到的核心问题是代码编辑器渲染不稳定:不同设备上表现差异大,有时能立即加载,有时要等30秒,甚至完全加载失败。

代码单元格组件代码

"use client";

function PythonCompiler() {
  const [input, setInput] = useState("");
  const {
    runPython,
    stdout,
    stderr,
    isLoading,
    isReady,
    isRunning,
    isAwaitingInput,
    sendInput,
  } = usePython();

  useEffect(() => {
    navigator.serviceWorker
      .register("/react-py-sw.js")
      .then((registration) =>
        console.log(
          "Service Worker registration done!: ",
          registration.scope
        )
      )
      .catch((err) =>
        console.log("Service Worker registration не удалась :(    ): ", err)
      );
  }, []);

  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    // await ensurePyodideHttp(); 
    runPython(input);
  };

  const handleEditorChange = useCallback((val: string, viewUpdate: any) => {
    console.log("val:", val);
    setInput(val);
  }, []);

  return (
    <>
      <Flex justify="center" pt={5} pb={1}>
        <div className="relative color-red mb-10 flex flex-col">
          <form onSubmit={handleSubmit}>
            <div className="p-4 sm:w-full md:min-w-[43em] bg-gray-800 rounded-md shadow-lg shadow-gray-700/50 width-100%">
              <CodeMirror
                value={input}
                height="100%"
                width="100%"
                extensions={[python()]}
                onChange={handleEditorChange}
                theme={dracula}
                style={{ fontSize: "1.2em" }}
                placeholder="Здесь можно писать и запускать код"
              />
            </div>

            <input
              type="submit"
              value={!isRunning ? "Запуск кода" : "В процессе..."}
              disabled={isLoading || isRunning}
              className={`px-4 my-3 py-2 rounded-md text-white font-semibold 
    ${
      isLoading || isRunning
        ? "bg-gray-400 cursor-not-allowed"
        : "bg-blue-500 hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-600 focus:ring-opacity-50"
    }
  `}
            />
          </form>
          {isLoading ? <p>Loading...</p> : <p>Ready!</p>}
          {isAwaitingInput && (
            <form
              onSubmit={(e) => {
                e.preventDefault();
                const form = e.target as HTMLFormElement;
                const inputElement = form.elements.namedItem(
                  "input"
                ) as HTMLInputElement;
                if (inputElement) {
                  sendInput(inputElement.value);
                  inputElement.value = "";
                }
              }}
            >
              
              <Input
                name="input"
                type="text"
                placeholder="Ввод: "
                size="md"
                borderColor="gray.300"
                focusBorderColor="blue.500"
                borderRadius="md"
                mb={3}
              />
              <Button my={2} type="submit" colorScheme="blue" size="md">
                Input
              </Button>
            </form>
          )}

            <code>
              <Text sx={{ userSelect: "none" }} color={"gray.500"}>
                Result:{""}
              </Text>
              {stdout}
            </code>
          
            <code>
              <Text sx={{ userSelect: "none" }} color={"gray.500"}>
                Error:{""}
              </Text>
              {stderr}
            </code>
          
        </div>
      </Flex>
    </>
  );
}

export default PythonCompiler;

pyodide-http 相关代码

之前控制台提示需要这个模块,安装后没看到改善,相关代码如下:

const ensurePyodideHttp = async () => {
    if (isReady) {
      try {
        await runPython(`
          import micropip
          await micropip.install("pyodide-http")
        `);
        console.log("pyodide-http loaded successfully");
      } catch (error) {
        console.error("Error loading pyodide-http:", error);
      }
    }
  };

排查与解决建议

  • Service Worker 注册优化

    • 把service worker注册逻辑移到_app.tsx中全局执行,避免组件渲染时才触发注册,导致pyodide加载延迟。
    • 检查react-py-sw.js是否放在Next.js的public目录下,路径错误会导致注册失败,直接影响pyodide初始化。
  • react-py 初始化优化

    • pyodide体积较大(约几十MB),网络和设备性能差异会导致加载波动。可以在_app.tsx中提前触发pyodide初始化,比如用useEffect在应用启动时预加载资源。
    • 升级react-py到最新稳定版,排查是否存在已知的初始化bug。
  • CodeMirror 渲染排查

    • 先简化编辑器配置:去掉theme={dracula}和自定义style,测试基础渲染是否稳定,再逐步添加配置,定位是否是主题/样式导致的渲染问题。
    • 给CodeMirror设置固定高度(比如height="400px"),避免父容器尺寸变化引发的布局重排,导致渲染延迟。
  • pyodide-http 安装逻辑调整

    • 把ensurePyodideHttp放在监听isReady变化的useEffect中,确保pyodide初始化完成后自动安装,而不是在代码提交时才处理:
      useEffect(() => {
        if (isReady) {
          ensurePyodideHttp();
        }
      }, [isReady]);
      
    • 可以给安装逻辑添加超时处理,避免阻塞编辑器渲染。
  • 减少不必要重渲染

    • 用React.memo包裹PythonCompiler组件,减少无关状态变化导致的重渲染:
      export default React.memo(PythonCompiler);
      

内容的提问来源于stack exchange,提问作者Владислав Мокер

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 20:04:51