Claude AI の Artifacts の仕組みを調べたら面白かった
tl;dr
- Claude AI の Artifacts で tsx の React コードをプレビューできた
- 中身は Next.js の Static Build の成果物
- おそらく Next.js の開発サーバーをプロダクションにデプロイし、前段の Cloudflare でキャッシュしていそう
claude.ai の Feature Preview で Artifacts を有効にすると、React のコードがプレビューできるのに気づいた。
HTML をプレビューできたのを知っていたが、TSX はどこで処理しているのだろう?と疑問に思って、中身を覗いてみた。
iframe 下で Next.js の静的ビルドモードの成果物を表示している。
つまり、生成されたコードを何らかの形で(開発モードの?) Next.js に渡して、その結果をキャッシュしているのではないか。
試しに中身がほとんど同じコードを生成させてみたが(カウンターの初期値が1)、異なる成果物で、チャンクがほとんど一致した。
つまり、同一設定の Next.js サーバーがコンテンツを吐き出し続けている。
おそらく /src/pages/[id].tsx
に生成されたコードを書き込むか、仮想的なFSを用意して(全部一台のマシンのローカルFSで管理してるとは思えないので、こっちな気がする)、初回だけ Next.js で生成し、残りはキャッシュしているのだろう。 traceroute www.claudeusercontent.com
で確かめると、anthropic のアプリケーションサーバの前段に cloudflare がいた。
おそらく cloudflare workers ではない。開発モードの Next.js は動的 eval が禁止されているので、 cloudflare workers にデプロイ出来ない。
最初は ISR かと思ったが、ISR は props の差分は吸収できるが、コードそのものを動的評価できない。
セキュリティ的な懸念点として、pages のnext の機能や SSR 時に攻撃できるのでは、と思って試したが、流石にクライアントでしか評価しないようになっていた。
例えばこういうコードを評価させた。
import React from 'react';
export async function getStaticProps(context) {
return {
props: { foo: 1 },
}
}
const Counter = (props) => {
return (
<div className="p-4 bg-gray-100 rounded-lg shadow-md">
<h2 className="text-xl font-bold mb-2">Counter Component</h2>
<div className="bg-white p-2 rounded border border-gray-300">
<pre className="text-sm">
<code>{JSON.stringify(props, null, 2)}</code>
</pre>
</div>
<p className="mt-2 text-sm text-gray-600">
Note: getStaticProps is not executed in this client-side environment.
</p>
</div>
);
};
export default Counter;
getStaticProps を通らないので出力は {}
export default function Counter(props) {
return <pre><code>{Object.keys(globalThis)}</code></pre>
}
サーバーサイドの globalThis を取れないかと思ったが、ブラウザコンテキストしか評価されなかった。
ライブラリは使えるか
共通の node_modules で管理してるはずなので、ライブラリを npm install した際に副作用起きるはず、と思って試したが外部ライブラリは参照できないようだった。
というわけで、TSX+Tailwind でマークアップされたコンポーネントを生成させる環境として便利、という話