Skip to content

heiwa4126/vite-react-esm1

Repository files navigation

vite-react-esm1

(2025-04)

React v19 から UMD ビルドが廃止になって、 ESM ベースの CDN が推奨になりました。 (参照: UMD ビルドの削除)

importmap を使って、お手軽に ESM CDN 対応にしてみましょう。 importmap を使うと、既存の js, ts, jsx, tsx 文中の import 文を修正することなく、モジュールの読込元を変更できます。

参考: 8.1.5.2 Import maps - HTML Living Standard

実習

ここでは pnpm を使いますが、npm や bun でも手順はおおむね一緒です。

まず vite create でプロジェクトを作成します。

2025 年 4 月現在、create vite の react テンプレートは React 19 を最初から使うようになっていました。 package.json を確認し、もし 19 でなければ適宜修正してください。

pnpm create vite vite-react-esm1 --template react-ts
cd vite-react-esm1
pnpm install
pnpm run build && pnpm run preview

http://localhost:4173/ を開いて、動作確認してください。 よくある Vite のサンプルが見えるはずです。

次はこれを ESM 対応にしてみます。

まず、./index.html を編集して、</head> の直前に インポートマップを追加しましょう。

<head>
  /*...略...*/
  <script type="importmap">
    {
      "imports": {
        "react": "https://esm.sh/react@19",
        "react-dom/client": "https://esm.sh/react-dom@19/client"
      }
    }
  </script>
</head>

つぎに ./vite.config.ts を編集して defineConfig に Rollup のオプションを追加してください。

export default defineConfig({
  //...略...
  build: {
    rollupOptions: {
      external: ["react", "react-dom/client"],
    },
  },
});

ビルド時の バンドルから除外するのは src/main.tsxなどで import しているモジュールをそのまま書きます。 'react-dom/client' のかわりに 'react-dom' や 'react-dom/*' とは書けないようです。

あとは pnpm run build && pnpm run preview で、

を確認してください。

これでバンドルと ESM CDN の両方の利点を生かしたフロントエンドが出来上がりました。

いまのところの欠点

  • pnpm run dev で開発時にも importmap を呼んでしまうかもしれない (なぜ「かもしれない」かというと、開発者ツールで見ると、importmap の部分を読んでる形跡がないから)。
  • モジュールのリストのメンテが手動。プラグインで自動処理とかできればいいんですが。
  • 「Next.js で SSR」とかの場合どうなるか不明。まあ動くとは思えませんが。

?dev

中身を見れば一目瞭然ですが、esm.sh では ?dev をつけると開発版を取得します。

https://esm.sh/react@19/?dev

/* esm.sh - [email protected] */
export * from "/[email protected]/es2022/react.development.mjs";
export { default } from "/[email protected]/es2022/react.development.mjs";

https://esm.sh/react@19

/* esm.sh - [email protected] */
export * from "/[email protected]/es2022/react.mjs";
export { default } from "/[email protected]/es2022/react.mjs";

参照: ESM>CDN の "Development Build" の節

esm.sh 以外の importmap 対応 CDN

importmap 対応をうたっている CDN は以下のものがあります。

ただ両方とも 2025 年 4 月現在、React 19 は見つかりませんでした。

jsDelivr では

<script type="importmap">
  {
    "imports": {
      "react": "https://cdn.jsdelivr.net/npm/react@19/+esm",
      "react-dom/client": "https://cdn.jsdelivr.net/npm/react-dom@19/client/+esm"
    }
  }
</script>

のように書けば、とりあえず動きます (ESM で import に書くのと同じ URL)。 複雑な依存を持つモジュールで動くかは確認してません。 https://cdn.jsdelivr.net/npm/react-dom@19/client/+esm の冒頭を見ると、 それなりに変換しているようなので、動く可能性は高いです。 esm.sh や jsdelivr は、例えば lodash のような cjs でしか提供されていないモジュールも、esbuild や rollup で ESM 化しているようです。

参考: Migrate from esm.sh to jsDelivr

一方 unpkg や cdnjs は明示的に ESM を指定する方法がないようです。 unpkg では「?module を付ける or .mjs を直接指定」で行ける、という話を見つけましたが未確認。

esm.sh/tsx を使えば JSX が <script> に書ける

その他、esm.sh で面白いのは esm.sh/tsxUsing esm.sh/tsx にコピペで実行できる HTML が載ってるので、試してみてください。

サンプルは esm-dev/tsx: A TSX transpiler for esm.sh services. の方がちょっと新しい。

About

importmapでお手軽ESM CDN対応にする練習

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published