{"id":31405402,"url":"https://github.com/nitoh-hisashi/ioniccdn","last_synced_at":"2025-09-29T17:17:51.545Z","repository":{"id":305849393,"uuid":"1024138779","full_name":"NITOH-Hisashi/IonicCDN","owner":"NITOH-Hisashi","description":"IonicとReactで仮想スクロール","archived":false,"fork":false,"pushed_at":"2025-07-26T12:59:18.000Z","size":23,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-27T23:34:50.147Z","etag":null,"topics":["cdn","ionic","javascript","react","reactjs"],"latest_commit_sha":null,"homepage":"https://nitoh-hisashi.github.io/IonicCDN/","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NITOH-Hisashi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-22T08:39:40.000Z","updated_at":"2025-07-23T05:45:20.000Z","dependencies_parsed_at":"2025-07-22T10:49:17.017Z","dependency_job_id":null,"html_url":"https://github.com/NITOH-Hisashi/IonicCDN","commit_stats":null,"previous_names":["nitoh-hisashi/ioniccdn"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/NITOH-Hisashi/IonicCDN","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NITOH-Hisashi%2FIonicCDN","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NITOH-Hisashi%2FIonicCDN/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NITOH-Hisashi%2FIonicCDN/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NITOH-Hisashi%2FIonicCDN/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NITOH-Hisashi","download_url":"https://codeload.github.com/NITOH-Hisashi/IonicCDN/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NITOH-Hisashi%2FIonicCDN/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":277551827,"owners_count":25837757,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-29T02:00:09.175Z","response_time":84,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cdn","ionic","javascript","react","reactjs"],"created_at":"2025-09-29T17:17:46.109Z","updated_at":"2025-09-29T17:17:51.539Z","avatar_url":"https://github.com/NITOH-Hisashi.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# IonicCDN\nIonicとReactで仮想スクロール\n\n## React.js を CDN 経由で使う\n\n`\u003cscript type=\"text/babel\"\u003e` という記述は、React.js を CDN 経由で使う際に JSX（JavaScript XML）をブラウザ上で直接変換・実行するための重要な指定です。\n\n---\n\n### 🧠 背景と目的\n\n通常、React.js を使うには Node.js 環境や npm を使ったプロジェクト構成が必要ですが、記事では「小規模でサクッと開発したい」というニーズに応える方法として、CDN を使った最小構成を紹介しています。\n\nその中で `\u003cscript type=\"text/babel\"\u003e` は、JSX をブラウザ上で直接 JavaScript に変換するために使われます。\n\n---\n\n### 🔍 役割と仕組み\n\n#### JSXの変換\n- JSX は HTML に似た構文で React コンポーネントを記述できるが、ブラウザはそのままでは理解できない。\n- Babel（CDN経由で読み込む `babel-standalone`）が JSX を JavaScript に変換する。\n- `\u003cscript type=\"text/babel\"\u003e` によって、Babel がそのスクリプトブロック内のコードを変換対象として認識する。\n\n#### 実行の流れ\n1. **CDNでライブラリを読み込む**\n   ```html\n   \u003cscript src=\"https://unpkg.com/react@18/umd/react.production.min.js\" crossorigin\u003e\u003c/script\u003e\n   \u003cscript src=\"https://unpkg.com/react-dom@18/umd/react-dom.production.min.js\" crossorigin\u003e\u003c/script\u003e\n   \u003cscript src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"\u003e\u003c/script\u003e\n   ```\n   - React本体、DOM操作用のReactDOM、そしてBabelを読み込む。\n\n2. **JSXを含むスクリプトを記述**\n   ```html\n   \u003cscript type=\"text/babel\"\u003e\n     const App = () =\u003e {\n       return (\n         \u003cdiv\u003e\n           hello\n           \u003cChildComponent greeting='おはよう' /\u003e\n         \u003c/div\u003e\n       );\n     };\n\n     const ChildComponent = ({ greeting }) =\u003e {\n       return \u003ch2\u003e{greeting}\u003c/h2\u003e;\n     };\n\n     const container = document.getElementById('root');\n     const root = ReactDOM.createRoot(container);\n     root.render(\u003cApp /\u003e);\n   \u003c/script\u003e\n   ```\n   - JSXでReactコンポーネントを定義し、DOMにレンダリングする。\n\n---\n\n### ⚠️ 注意点\n\n- **開発用途向け**：`babel-standalone` は本番環境には向いていません。変換処理がブラウザ上で行われるため、パフォーマンスやセキュリティの観点からも避けるべきです。\n- **構文エラーに注意**：JSXはHTMLに似ているが、JavaScriptの構文として扱われるため、閉じタグや属性の記述ミスに注意が必要です。\n\n---\n\n### 🛠️ まとめ\n\n`\u003cscript type=\"text/babel\"\u003e` は、React.js を CDN 経由で使う際に JSX を直接ブラウザで変換・実行するための仕組みです。Node.js や npm を使わずに、手軽に React の開発を始めたいときに便利ですが、あくまで学習やプロトタイプ向けの手法です。\n\n---\n\n## 📦 JSX を外部ファイルに分離する方法（CDN構成）\n\n### 1. JSXファイルを作成する\nたとえば、`app.jsx` というファイルを作成し、以下のように記述します：\n\n```jsx\nconst ChildComponent = ({ greeting }) =\u003e {\n  return \u003ch2\u003e{greeting}\u003c/h2\u003e;\n};\n\nconst App = () =\u003e {\n  return (\n    \u003cdiv\u003e\n      hello\n      \u003cChildComponent greeting=\"おはよう\" /\u003e\n    \u003c/div\u003e\n  );\n};\n\nconst container = document.getElementById('root');\nconst root = ReactDOM.createRoot(container);\nroot.render(\u003cApp /\u003e);\n```\n\n### 2. HTMLから読み込む\nHTML 側では Babel を使って JSX を変換するため、外部ファイルを `\u003cscript type=\"text/babel\" src=\"app.jsx\"\u003e\u003c/script\u003e` のように読み込みます：\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003cmeta charset=\"utf-8\" /\u003e\n    \u003ctitle\u003eReact CDN Example\u003c/title\u003e\n    \u003cscript src=\"https://unpkg.com/react@18/umd/react.production.min.js\" crossorigin\u003e\u003c/script\u003e\n    \u003cscript src=\"https://unpkg.com/react-dom@18/umd/react-dom.production.min.js\" crossorigin\u003e\u003c/script\u003e\n    \u003cscript src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"\u003e\u003c/script\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cdiv id=\"root\"\u003e\u003c/div\u003e\n    \u003cscript type=\"text/babel\" src=\"app.jsx\"\u003e\u003c/script\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n---\n\n### ⚠️ 注意点\n\n- **ローカルで動かす場合**：`app.jsx` を読み込むには、ローカルサーバー（例：PythonのHTTPサーバーなど）を使う必要があります。ファイルを直接開く（`file://`）では読み込めません。\n- **CORS制限**：外部ファイルを読み込む際、CORS（クロスオリジン）制限に注意してください。ローカルでの開発には `http-server` や `live-server` などが便利です。\n- **本番環境では非推奨**：Babelによるブラウザ上での変換は開発用途向けです。本番では事前にビルドして JS に変換しておくのが一般的です。\n\n---\n\n### ✅ まとめ\n\nJSX を外部ファイルに分離することは可能で、`\u003cscript type=\"text/babel\" src=\"...\"\u003e` を使えば HTML から読み込めます。ただし、ローカルサーバーの利用や開発用途に限定される点に注意が必要です。\n\nIonic Components を CDN で使う方法について、公式ドキュメントの内容をもとにわかりやすく解説します。\n\n---\n\n## 🚀 Ionic Components を CDN で使う方法\n\nIonic Framework は、CDN を使って **Angular・React・Vue などのフレームワークなしでも** HTML ページ上で直接使うことができます。これはプロトタイプやテスト環境に非常に便利です。\n\n### ✅ 必要なCDNリンク\n\n以下のコードを HTML の `\u003chead\u003e` に追加することで、Ionic のコアコンポーネントとスタイルを読み込めます：\n\n```html\n\u003c!-- Ionic Core JS (ESMと非ESM両方) --\u003e\n\u003cscript type=\"module\" src=\"https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.esm.js\"\u003e\u003c/script\u003e\n\u003cscript nomodule src=\"https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.js\"\u003e\u003c/script\u003e\n\n\u003c!-- Ionic CSS --\u003e\n\u003clink rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/@ionic/core/css/ionic.bundle.css\" /\u003e\n```\n\nこれだけで `\u003cion-button\u003e` や `\u003cion-card\u003e` などのコンポーネントが使えるようになります。\n\n---\n\n$## 🧪 使用例（Vanilla HTML）\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n  \u003chead\u003e\n    \u003cmeta charset=\"UTF-8\" /\u003e\n    \u003ctitle\u003eIonic CDN Example\u003c/title\u003e\n    \u003cscript type=\"module\" src=\"https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.esm.js\"\u003e\u003c/script\u003e\n    \u003cscript nomodule src=\"https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.js\"\u003e\u003c/script\u003e\n    \u003clink rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/@ionic/core/css/ionic.bundle.css\" /\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cion-button expand=\"block\" color=\"primary\"\u003eHello Ionic\u003c/ion-button\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\nこのように、フレームワークなしで Ionic コンポーネントを直接使えます。\n\n---\n\n### 📌 注意点\n\n- **ローカルで動かす場合はサーバーが必要**：ESM モジュールは `file://` では動作しないため、`http-server` や `live-server` などのローカルサーバーを使ってください。\n- **本番環境には不向き**：CDN構成は開発・テスト向けです。本番では npm を使ってビルドする方法が推奨されます。\n- **Ioniconsも使える**：アイコンを使いたい場合は以下を `\u003cbody\u003e` の最後に追加します：\n\n```html\n\u003cscript type=\"module\" src=\"https://cdn.jsdelivr.net/npm/ionicons/dist/ionicons/ionicons.esm.js\"\u003e\u003c/script\u003e\n\u003cscript nomodule src=\"https://cdn.jsdelivr.net/npm/ionicons/dist/ionicons/ionicons.js\"\u003e\u003c/script\u003e\n```\n\n---\n\n### 🧩 Ionic + React/Vue/Angular との違い\n\nCDN構成ではフレームワーク固有の機能（ルーティング、状態管理など）は使えません。より高度なアプリを作る場合は npm を使って `@ionic/react` や `@ionic/vue` を導入するのがベストです。\n\n---\n\nReact に Ionic Components を CDN 経由で組み込む方法について、公式ドキュメントの内容と React の基本構成を踏まえて解説します。\n\n---\n\n## ⚙️ Ionic Components を React + CDN 構成に追加する方法\n\n### ✅ 必要なCDNリンク（HTMLに追加）\n\nReact を CDN で使っている場合、以下の Ionic CDN を `\u003chead\u003e` に追加します：\n\n```html\n\u003c!-- Ionic Core JS --\u003e\n\u003cscript type=\"module\" src=\"https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.esm.js\"\u003e\u003c/script\u003e\n\u003cscript nomodule src=\"https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.js\"\u003e\u003c/script\u003e\n\n\u003c!-- Ionic CSS --\u003e\n\u003clink rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/@ionic/core/css/ionic.bundle.css\" /\u003e\n```\n\nこれで `\u003cion-button\u003e` や `\u003cion-card\u003e` などの Web Components が使えるようになります。\n\n---\n\n### 🧪 React + Ionic の使用例（CDN構成）\n\nReact を CDN で使っている前提で、JSX 内に Ionic コンポーネントを組み込む例です：\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003cmeta charset=\"UTF-8\" /\u003e\n    \u003ctitle\u003eReact + Ionic CDN\u003c/title\u003e\n    \u003c!-- React \u0026 Babel --\u003e\n    \u003cscript src=\"https://unpkg.com/react@18/umd/react.development.js\" crossorigin\u003e\u003c/script\u003e\n    \u003cscript src=\"https://unpkg.com/react-dom@18/umd/react-dom.development.js\" crossorigin\u003e\u003c/script\u003e\n    \u003cscript src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"\u003e\u003c/script\u003e\n\n    \u003c!-- Ionic --\u003e\n    \u003cscript type=\"module\" src=\"https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.esm.js\"\u003e\u003c/script\u003e\n    \u003cscript nomodule src=\"https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.js\"\u003e\u003c/script\u003e\n    \u003clink rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/@ionic/core/css/ionic.bundle.css\" /\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cdiv id=\"root\"\u003e\u003c/div\u003e\n\n    \u003cscript type=\"text/babel\"\u003e\n      const App = () =\u003e {\n        return (\n          \u003cdiv\u003e\n            \u003cion-button color=\"primary\"\u003eIonic Button\u003c/ion-button\u003e\n            \u003cion-card\u003e\n              \u003cion-card-header\u003e\n                \u003cion-card-title\u003eCard Title\u003c/ion-card-title\u003e\n              \u003c/ion-card-header\u003e\n              \u003cion-card-content\u003eThis is Ionic content inside React!\u003c/ion-card-content\u003e\n            \u003c/ion-card\u003e\n          \u003c/div\u003e\n        );\n      };\n\n      const root = ReactDOM.createRoot(document.getElementById('root'));\n      root.render(\u003cApp /\u003e);\n    \u003c/script\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n---\n\n### 📌 注意点\n\n- Ionic の Web Components は **カスタム要素（Custom Elements）** なので、React から直接使えます。\n- ただし、**イベントハンドリング（onClickなど）** や **状態管理** は React 側で行う必要があります。\n- Ionic の一部機能（`ion-content` や `ion-page` など）は、モバイルライクな UI を構成するために使われます。必要に応じて追加してください。\n\n---\n\n### 🧩 Ionic React（npm構成）との違い\n\nCDN構成では `@ionic/react` パッケージを使わないため、以下のような高度な機能は使えません：\n\n| 機能                     | CDN構成 | npm構成（@ionic/react） |\n|--------------------------|---------|--------------------------|\n| JSXでの型補完            | ❌      | ✅                       |\n| React Routerとの統合     | ❌      | ✅                       |\n| Ionic専用のライフサイクル | ❌      | ✅                       |\n| 仮想スクロール（Virtuoso）| ⚠️ 手動対応 | ✅ 統合済み              |\n\n---\n\n### 🧠 まとめ\n\nReact + CDN 構成でも Ionic の Web Components を使うことは可能です。簡単な UI を素早く構築したい場合に便利ですが、より複雑なアプリを作る場合は `@ionic/react` を使った npm 構成が推奨されます。\n\nCDN構成で仮想スクロールを使いたい場合、残念ながら公式の推奨ライブラリである [Virtuoso](https://virtuoso.dev/) は **npm環境専用** であり、CDNでは直接利用できません。Ionic公式ドキュメントでも、`react-virtuoso` の使用には `npm install` が必要と明記されています[^1]。\n\n---\n\n## ❌ CDN構成での制約\n\n| 機能 | CDN構成 | npm構成 |\n|------|----------|----------|\n| Virtuosoによる仮想スクロール | 利用不可 | 利用可能 |\n| `ion-virtual-scroll`（旧機能） | 廃止済み | 廃止済み |\n| 独自実装による仮想スクロール | ⚠️ 可能だが手動対応 | ✅ 可能 |\n\n---\n\n## 🛠️ CDN構成で仮想スクロールを実現する代替案\n\nCDN構成で仮想スクロールを使いたい場合は、以下のような **手動実装** が必要です：\n\n### 1. スクロール領域を制限し、表示アイテムを動的に切り替える\n\n```html\n\u003cdiv id=\"scroll-container\" style=\"height: 400px; overflow-y: auto;\"\u003e\n  \u003cdiv id=\"visible-items\"\u003e\u003c/div\u003e\n\u003c/div\u003e\n\n\u003cscript type=\"text/babel\"\u003e\n  const totalItems = 10000;\n  const itemHeight = 40;\n  const visibleCount = 20;\n\n  const ScrollList = () =\u003e {\n    const [startIndex, setStartIndex] = React.useState(0);\n\n    React.useEffect(() =\u003e {\n      const container = document.getElementById('scroll-container');\n      container.addEventListener('scroll', () =\u003e {\n        const scrollTop = container.scrollTop;\n        const newStart = Math.floor(scrollTop / itemHeight);\n        setStartIndex(newStart);\n      });\n    }, []);\n\n    const items = [];\n    for (let i = startIndex; i \u003c startIndex + visibleCount; i++) {\n      items.push(\n        \u003cion-item key={i}\u003e\n          \u003cion-label\u003e{`Item ${i}`}\u003c/ion-label\u003e\n        \u003c/ion-item\u003e\n      );\n    }\n\n    return \u003cdiv style={{ height: totalItems * itemHeight + 'px' }}\u003e{items}\u003c/div\u003e;\n  };\n\n  ReactDOM.createRoot(document.getElementById('visible-items')).render(\u003cScrollList /\u003e);\n\u003c/script\u003e\n```\n\n\u003e この方法は簡易的な仮想スクロールで、パフォーマンスやUXは Virtuoso に劣ります。\n\n---\n\n### ✅ 結論とおすすめ\n\n- CDN構成では **Virtuosoは使えない**。\n- 仮想スクロールを使いたいなら、**npm構成に移行するのが最も現実的**。\n- どうしてもCDNでやりたい場合は、**手動でスクロールイベントを監視して表示アイテムを切り替える**必要があります。\n\n---\n\n[^1]: [Ionic公式ドキュメント - 仮想スクロール](https://ionicframework.com/docs/ja/react/virtual-scroll)\n\nCDN構成で仮想スクロールを使う場合、スクリプトを HTML から分離するには、JSX を外部ファイルにして `\u003cscript type=\"text/babel\" src=\"...\"\u003e` で読み込む方法が使えます。ただし、Virtuoso のような高度な仮想スクロールライブラリは CDN では利用できないため、**手動で仮想スクロールを実装する**必要があります。\n\n---\n\n## 📁 スクリプトを分離する方法（CDN構成）\n\n### 1. 外部ファイルを作成（例：`scroll-list.jsx`）\n\n```jsx\nconst totalItems = 10000;\nconst itemHeight = 40;\nconst visibleCount = 20;\n\nconst ScrollList = () =\u003e {\n  const [startIndex, setStartIndex] = React.useState(0);\n\n  React.useEffect(() =\u003e {\n    const container = document.getElementById('scroll-container');\n    container.addEventListener('scroll', () =\u003e {\n      const scrollTop = container.scrollTop;\n      const newStart = Math.floor(scrollTop / itemHeight);\n      setStartIndex(newStart);\n    });\n  }, []);\n\n  const items = [];\n  for (let i = startIndex; i \u003c startIndex + visibleCount; i++) {\n    items.push(\n      \u003cion-item key={i}\u003e\n        \u003cion-label\u003e{`Item ${i}`}\u003c/ion-label\u003e\n      \u003c/ion-item\u003e\n    );\n  }\n\n  return \u003cdiv style={{ height: totalItems * itemHeight + 'px' }}\u003e{items}\u003c/div\u003e;\n};\n\nReactDOM.createRoot(document.getElementById('visible-items')).render(\u003cScrollList /\u003e);\n```\n\n### 2. HTMLファイルで読み込む\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003cmeta charset=\"UTF-8\" /\u003e\n    \u003ctitle\u003eCDN Virtual Scroll\u003c/title\u003e\n    \u003c!-- React \u0026 Babel --\u003e\n    \u003cscript src=\"https://unpkg.com/react@18/umd/react.development.js\" crossorigin\u003e\u003c/script\u003e\n    \u003cscript src=\"https://unpkg.com/react-dom@18/umd/react-dom.development.js\" crossorigin\u003e\u003c/script\u003e\n    \u003cscript src=\"https://unpkg.com/babel-standalone@6/babel.min.js\"\u003e\u003c/script\u003e\n\n    \u003c!-- Ionic --\u003e\n    \u003cscript type=\"module\" src=\"https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.esm.js\"\u003e\u003c/script\u003e\n    \u003cscript nomodule src=\"https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.js\"\u003e\u003c/script\u003e\n    \u003clink rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/@ionic/core/css/ionic.bundle.css\" /\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cdiv id=\"scroll-container\" style=\"height: 400px; overflow-y: auto;\"\u003e\n      \u003cdiv id=\"visible-items\"\u003e\u003c/div\u003e\n    \u003c/div\u003e\n\n    \u003c!-- JSXスクリプトの読み込み --\u003e\n    \u003cscript type=\"text/babel\" src=\"scroll-list.jsx\"\u003e\u003c/script\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n---\n\n### ✅ ポイント\n\n- JSXファイルは `.jsx` 拡張子で保存し、`type=\"text/babel\"` で読み込む。\n- ローカルで動かす場合は `http-server` や `live-server` などのローカルサーバーが必要。\n- CDN構成では `react-virtuoso` は使えないため、スクロールイベントを使った手動実装が必要。\n\n---\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnitoh-hisashi%2Fioniccdn","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnitoh-hisashi%2Fioniccdn","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnitoh-hisashi%2Fioniccdn/lists"}