[React] 在Next.js 13中运行Python
有时候当我告诉别人时,他们会感到惊讶,但事实上,Next.js中可以运行Python环境。
在浏览器上使用Python环境的Pyodide得益于WASM技术,而在React中使用时,也存在提供方便的钩子功能的npm包react-py。
与上一篇文章相同,这是一个仅在客户端工作的机制,但是这次我打算使用Next.js 13的客户端组件功能来更加清晰地处理导入等操作。
今天的流程将会是这样的:
-
- 从Next.js 13(TypeScript)的模板开始
准备一个能够输入和执行Python代码的组件,使用react-py
使用Chakra来简化并改善界面外观的方法
从Next.js 13(TypeScript)的模板开始
现在,Next.js 13和TypeScript会自动安装。
yarn create next-app
当然也可以使用npm、pnpm或者其他工具。本文将使用yarn进行示范。
另外,我认为你可能需要在各种情况下做出选择,但我会分享与默认选项不同的自己的选择:
-
- Would you like to use Tailwind CSS with this project? › No
-
- Chakraを使う予定でしたので、Tailwindは不要だと思いました(Python環境の部分に影響ありません)
-
- Would you like to customize the default import alias? › Yes
-
- What import alias would you like configured? … @/*
- プロジェクト内のコンポーネントがインポートしやすくなります(Python環境の部分に影響ありません)
使用react-py为Python代码准备一个能够输入和执行的组件。
首先让我们安装react-py。
yarn add react-py
在文档中,只介绍了Next.js 13中在客户端组件中的使用方式。但在Next.js 12中,可以使用next/dynamic进行导入。如果您想在现有项目中直接使用react-py,请参考关于Next.js + p5.js的文章。方法是相同的。
我想介紹一下在这次中故意使用了最新的Next.js 13、更简单的方法。刚才我已经提供了文档链接,但首先让我们在想要使用Python环境的组件或页面的第一行添加’use client’以创建一个客户端组件。客户端组件将不再是Next.js在服务器端生成的对象,所以将不再需要next/dynamic等组件。
插入Python提供者
我们将页面或组件的顶部设置为类似Python的客户端组件。
'use client'
import { PythonProvider } from 'react-py'
让我们将该Python Provider添加到本页面的输出中。请将其包围在使用react-py的hook的组件周围。
export default function Home() {
return (
<PythonProvider>
<main>
<Codeblock />
</main>
</PythonProvider>
)
}
Codeblock将成为本教程的任意组件。
代码块组件 (Codeblock组件)
我认为React-py有很多用途,但这次让我们按照文档的通知,将
<span class=”k”>import</span> <span class=”p”>{</span> <span class=”nx”>usePython</span> <span class=”p”>}</span> <span class=”k”>from</span> <span class=”dl”>'</span><span class=”s1″>react-py</span><span class=”dl”>'</span>
</code></pre>
<p>在组件的定义中,使用usePython。</p>
<pre class=”post-pre”><code><span class=”k”>export</span> <span class=”k”>default</span> <span class=”kd”>function</span> <span class=”nf”>Codeblock</span><span class=”p”>()</span> <span class=”p”>{</span>
<span class=”kd”>const</span> <span class=”p”>{</span> <span class=”nx”>runPython</span><span class=”p”>,</span> <span class=”nx”>stdout</span><span class=”p”>,</span> <span class=”nx”>stderr</span><span class=”p”>,</span> <span class=”nx”>isLoading</span><span class=”p”>,</span> <span class=”nx”>isRunning</span> <span class=”p”>}</span> <span class=”o”>=</span> <span class=”nf”>usePython</span><span class=”p”>()</span>
<span class=”k”>return </span><span class=”p”>(</span>
<span class=”p”><></span>
…
<span class=”p”></></span>
<span class=”p”>)</span>
<span class=”p”>}</span>
</code></pre>
<p>获取:</p>
<ul class=”post-ul”>
<p>runPython: (code: string) => Promise<void>: Pythonコードを渡すと実行してくれる関数</p>
<p>stdout: string: Pythonの標準出力</p>
<p>stderr: string: Pythonの標準エラー出力</p>
<p>isLoading: boolean: Python環境を読み込み中かどうか(WASM自体がcdn.jsdelivr.netから読み込まれます)</p>
<p>isRunning: boolean: Python環境が処理中かどうか
</ul>
<p>我会根据需要使用Python中可以获取的其他常量和函数,比如isReady之类的。</p>
<h2>使用脉轮可以简单地改善外观</h2>
<p>最后,虽然不是主题,但我想用Chakra UI来实现。由于我第一次在Next.js 13中尝试使用Chakra UI,所以我学到了一些东西,我想简单分享一下。</p>
<p>由于与Pyodide没有直接关系,如果您要使用不同的Web组件,您可以不必读下面的内容。虽然我认为形式上还是需要处理一下,我试着用一种相对简单的方法来解决。</p>
<p>首先,让我们安装Chakra等软件。</p>
<pre class=”post-pre”><code>yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion
</code></pre>
<p>下一个是,在 react-py 中有一个名为 PythonProvider 的组件,就像 Chakra 中有一个名为 ChakraProvider 的组件一样。我想要用这个组件来包裹使用 Chakra 组件的部分。</p>
<p>我对Next.js 13的layout.tsx进行了以下更改:</p>
<pre class=”post-pre”><code><span class=”k”>import</span> <span class=”p”>{</span> <span class=”nx”>ChakraProvider</span> <span class=”p”>}</span> <span class=”k”>from</span> <span class=”dl”>'</span><span class=”s1″>@/tools/chakra-client-components</span><span class=”dl”>'</span>
<span class=”k”>export</span> <span class=”k”>default</span> <span class=”kd”>function</span> <span class=”nf”>RootLayout</span><span class=”p”>({</span>
<span class=”nx”>children</span><span class=”p”>,</span>
<span class=”p”>}:</span> <span class=”p”>{</span>
<span class=”nl”>children</span><span class=”p”>:</span> <span class=”nx”>React</span><span class=”p”>.</span><span class=”nx”>ReactNode</span>
<span class=”p”>})</span> <span class=”p”>{</span>
<span class=”k”>return </span><span class=”p”>(</span>
<span class=”p”><</span><span class=”nt”>html</span><span class=”p”>></span>
<span class=”p”><</span><span class=”nt”>head</span><span class=”p”>></span>
<span class=”p”><</span><span class=”nt”>title</span><span class=”p”>></span>Next.js 13 + Chakra + react-py<span class=”p”></</span><span class=”nt”>title</span><span class=”p”>></span>
<span class=”p”></</span><span class=”nt”>head</span><span class=”p”>></span>
<span class=”p”><</span><span class=”nt”>body</span><span class=”p”>></span>
<span class=”p”><</span><span class=”nc”>ChakraProvider</span><span class=”p”>></span><span class=”si”>{</span><span class=”nx”>children</span><span class=”si”>}</span><span class=”p”></</span><span class=”nc”>ChakraProvider</span><span class=”p”>></span>
<span class=”p”></</span><span class=”nt”>body</span><span class=”p”>></span>
<span class=”p”></</span><span class=”nt”>html</span><span class=”p”>></span>
<span class=”p”>)</span>
<span class=”p”>}</span>
</code></pre>
<p>由于ChakraProvider功能强大,不仅限于客户端组件使用,因此不需要将RootLayout设置为客户端组件。可以同时在服务器端生成和使用Chakra。</p>
<p>请参考Chakra的文档和已完成组件的代码:</p>
<ul class=”post-ul”>
page.tsx<br />
Codeblock.tsx
</ul>
<p>需要特别注意的一点是,HTML5的textarea标签的disabled属性在Chakra的Textarea组件中应该使用isDisabled: boolean。</p>
<h2>结束时</h2>
<p>我能够在浏览器上使用Next.js而无需使用外部API来执行Python脚本。此外,我还能够使用Next.js 13的新客户端组件来轻松导入只能在浏览器端使用的组件和hook。</p>
<p>由于Pyodide具有安装任何Python包等功能,所以您可以做出一些出乎意料的操作,因此在不想将用户原始数据发送到外部API的情况下,积极考虑使用Pyodide是一个值得思考的选择。</p>
<p>如果对示例库感兴趣,请参考一下。如果有任何疑问或要求,请在评论或Twitter上与我联系,我会很高兴解答。</p>