2026年1月14日水曜日

React-TailwindでCDN経由で使ってみる

Reactを使ってみよう!

今回はいたって単純React使ってみようという話です。
CDN経由で使えるのでどんな感じかを直ぐに試せるのは本当に良い時代です。
一応順を追って説明しますね

CDN (Contents Delivery Network) とは

まずコンテンツ・デリバリー・ネットワークで使えるというのがどういうことかというと、通常ライブラリとかフレームワークはダウンロードしてきてサーバーアップロードして参照したりしないといけない。
正直面倒臭いし、ブログなどではそもそもサーバにファイルが置けない。
そんな時にCDNです。
CDNは超簡単に言えば直リンクです
JSとかcssとかに直リンクして必要な結果だけを貰う。
ただし、昨今のCDNはデータサイズが大きいので重いです。例えば、Tailwindcssとかはcssって名前ではあるものの実際にはjsを経由してcssのデータを貰う形です。
全乗せのcss情報が来るのでサイズが大き目でリンク時のコンソールにもCDNでの本番運用だと遅いから推奨しないって内容の文字が裏で表示されます
他にも少し問題がありますが一旦後で説明します。
取り合えず超簡単にまとめると「便利機能がリンクするだけで使える様になる」です。

Reactとは

さて、本題のリアクトとはjavascriptのフレームワークです。
jsxで記述する事でタグとjavascriptを一つにまとめる事が出来ます。
初見では相当気持ち悪さを感じますがみんながみんな慣れるというので慣れなんだと思います。
また、Tailwindとの相性がよくcssを別途使わなくても短い記述でstyleも含めて記述する事が出来ます。クラス名を考えなくて良いという事もあり開発速度が上がります。

CDNでReactで使う場合

先ほど「他にも少し問題が」って言いましたがCDN経由ビルドとなるのでmjsでは利用できません。
私は自作のDOMラッパーをインポートしたりするので最近はmjsが多かったのですが今回は使えません。
何故使えないのかというとまずjsxのアクセス方法が<script type="text/babel" src="jsx.js"></script>こんな感じですね。
babelに投げてビルドしてもらうという事ですね。投げたjsxはjavascriptとして返ってきて始めて動作するのですがbabel君は外部接続できないのでimport文が利用出来ません。
スクリプトのアクセス方法をmjsにするとそもそもbabelにデータが渡せません。

つまり変数がグローバル化してしまうという事です。
まぁ、それだけといえばそれだけです。

Reactのおおまかな流れ

①ReactDOMから必要な機能を取り出す

const { createRoot } = ReactDOM;

分割代入で取り出すのが一番楽かと思います。
一応、ReactDOMから取り出してるだけなので
const a=ReactDOM.createRootでも
const a=ReactDOM['createRoot']でもアクセスは可能です。

②コンポーネントを作る

例えば以下の様にfooterを作ってみます

const Footer = () => (
    <footer className="py-8 border-t border-[#1a1a1a] bg-[#050505]">
        <div className="max-w-[1280px] mx-auto px-5 text-center text-xs text-[#555]">
            <p>©black stray cat</p>
        </div>
    </footer>
);

定数にFooterを定義無名関数でそのまま内容を書きます。
ほぼほぼタグをそのまま記述可能ですがclassはバニラJavascriptで定義されているためJSXではclassNameにする必要があります。
ちなみに「ケースセンシティブ (case-sensitive)」なのでFooterの頭をFにする事でタグのfooterと別の判定になります。Reactは 「小文字で始まるものは通常のHTMLタグ」「大文字で始まるものはカスタムコンポーネント」 と自動で判別します。そのため、自作コンポーネントは必ず大文字で始める必要があります。

③レンダリングする

const footerEl = document.getElementById('footer-root');
if (footerEl) createRoot(footerEl).render(<Footer />);

処理的には先ずDOMを定義して次に存在確認存在したらレンダリング
先ほどReactDOMから取り出した機能を使います。
renderに指定する中身は定数に定義したコンポーネント名です。
今回で言えば「<Footer />」こうですね。

④html側

<div id="footer-root"></div>

こんな感じです
先ほどgetElementById指定した所に内容を生成します。
このdivの内側に予定と違う内容あれば全て書き換えます。

挙動だけを見るとinnerHTMLに近いものだと思ってもあまり問題ないです。
ただし内部的には仮想DOMで極力再利用する様に処理されます。
innerHTMLの場合は全て破棄された後に書き変わる処理である為Reactの方がメモリ効率が良いし高速です。

つまり、事前に使うhtmlを用意しておくと読み込みが早くなります。
基本的にはNext.jsを使う事になると思いますがhtmlが無くても生成はされますので試す分には問題ないです。

この様にしてcss-in-jsがコンポーネントとして分離サイト内でパーツとして利用できます。
新たにサイト等を作る時にも同様の機能が欲しい時全て込み込みで移植出来ます。

CDNでReactでモジュール

さて、React19では可能というか19以降はインポートでしか行けない。
しかもインラインでしかjsxをビルド出来ない。
パーツをインラインで書くなら意味がない。

さらに色々な問題が発生します。
相対パスが外のurlと相対になり参照が上手くいかないとか、CDNのTailwindが先に処理されてReact19内で使うstyleが用意されないといった問題が起きる。
一応TWの対応はできる
  <script>
    tailwind.config = {
      safelist: [
        'hidden',
        'md:block',
        'md:hidden',
        'block',
        'w-8',
        'h-8',
        'py-4',
        'bg-[#050505]',
        // 例えば事前に読み込む必要がでる
      ]
    }
  </script>
のように先に使うものを指定しておく・・・ただこれを手動でやるのはCDNの手軽さが損なわれる。TWの参照が前後するならもう普通のスタイルを埋め込んだ方が確実。

React19の一応使い方としてはまず呼び出しは
  <!-- importmap:React 19 -->
  <script type="importmap">
  {
    "imports": {
      "react": "https://esm.sh/react@19.2.0",
      "react-dom/client": "https://esm.sh/react-dom@19.2.0/client"
    }
  }
  </script>

  <!-- tsxでJSX変換 -->
  <script type="module" src="https://esm.sh/tsx"></script>
この様に変更します
コード呼びは
<script type="text/babel">ここにインラインで記述
そしてReact呼び出しは今回インポートに変わります
    import React, { useState } from "react";
    import { createRoot } from "react-dom/client";
JSXに基本的な記述変更ありません
CDNでReactをモジュールにするとかなり色々な相性が悪くなる
ただ、公式推奨はもう新しいReact19なんですよね・・・。

まとめ

cdnで使うという前提において
コードを外部参照できるのはReact18まで
この場合はTailwindもとても相性が良い

React19はコードを外置き出来ないインラインでしかjsxをビルド出来ない
コードを別ファイルで管理したい時の解決策は2つ
1.素直にReact18を使う(既にサポート終了ずみ余命のみ)
2.React19でjsxを記述せず純粋なjsモジュールとして使う

ただまぁReactをバニラjsのmjsで利用すると変化癖がつく可能性があるにはある
たぶん現在の一般的な使い方はjsxで記述するのが普通だろうし・・・。
やはりCDNは個人サイトとかで使う場合であってもお試しが限界かなぁ

0 件のコメント:

コメントを投稿