Skip to content

全プラグインテンプレートを webpack から Vite へ移行 - #62

Merged
kira924age merged 3 commits into
developfrom
feature/vite-migration
Aug 10, 2026
Merged

kira924age merged 3 commits into
developfrom
feature/vite-migration

Conversation

@kira924age

Copy link
Copy Markdown
Contributor

概要

CustomExitScreen だけが先行して Vite 化されていたため、残り 10 テンプレートも同じ構成に揃えました。これで全テンプレートがひとつのビルド構成を共有します。

変更内容

各プラグイン共通:

  • webpack + @module-federation/enhanced → Vite 6 + @module-federation/viteconfigs/federationConfig.jsvite.config.ts にインライン化
  • public/index.html → ルートの index.html。webpack MF 固有の非同期境界(src/index.tssrc/bootstrap.tsx)を廃し、src/main.tsx を素直なエントリに
  • scripts/{set_uuid,add_metadata,archive_dist}.js を ESM 化、uuidv4uuidset_uuidVITE_VERSION_ID も出力
  • jest + ts-jest + babel → vitest(babel 一式を削除)
  • src/types/declarations.d.ts を削除し vite/client の型に統一

lint は eslint + prettier のまま維持しています(biome への統一は別対応)。dev サーバのポートも従来どおり 3004 です。

挙動を揃えるために注意した点

1. CSS Modules の名前空間インポート

全ファイルが import * as styles from "./X.module.scss" を使っていました。webpack の css-loader v7 はケバブケースも名前付きエクスポートとして出すため、以下のような動的参照が成立していました。

  • styles["status-" + statusColor]
  • styles[preset] (preset には urth-staff-red などハイフン入りの値がある)

Vite は有効な JS 識別子のみを名前付きエクスポートにするため、そのままだとこれらが 静かに undefined になりスタイルが壊れます。全 24 箇所をデフォルトインポートに変更し、localsConvention: "camelCase" でケバブ/キャメル両方のキーを保持しました。

2. クラス名のソルト

webpack は localIdentHashSalt: VERSION_ID により、ホスト上で他プラグインとクラス名が衝突しないようにしていました。Vite に同等のオプションが無いため、generateScopedName[name]__[local]__[hash:base64:5] の命名規則とソルトを再現しています。

3. @import "~normalize.css"

~ は webpack 固有の解決記法のため、コンポーネント側の import "normalize.css" に置き換えました(読み込み順は維持)。

付随して修正した既存バグ

Module Federation の DTS 生成が失敗していたため、ビルドを通すのに必要な範囲で修正しています。いずれも移行が原因ではなく、元から npm run lint:tsc が失敗していた箇所です。

  • CustomChatModal.tsx — Props の MessageGroupsmessageGroups のタイポ。あわせて any[] を実際の型に置換
  • ParticleEffect.tsx — confetti オプションに型を付与
  • useReactionTutorial2.tsquerySelector<HTMLElement> に修正
  • CustomNearestUserProfile — CSS Modules の computed property 2 箇所を classNames(a, cond && b) 形式に
  • ToolbarButton.jsx — JSDoc で props に型付け(実行時の変更なし)

動作確認

Plugin build test
AdditionalToolbarButton
CustomChatButton
CustomEntryPanel
CustomLeaveButton ✅ (3)
CustomMegaphoneButton
CustomNearestUserProfile
CustomOverlay ✅ (2)
CustomProfileModal
CustomTutorial
CustomWebCameraButton

加えて、AdditionalToolbarButton(モーダル開閉まで)・CustomOverlay・CustomWebCameraButton はブラウザ実機で描画とスタイル適用を確認しました。

レビュー時に確認いただきたい点

mf-manifest.jsonremoteEntry.type"global" から "module"(ESM)に変わります。 これは @module-federation/vite の仕様で、先行 Vite 化済みの CustomExitScreen も同じです。metatell ホスト側がこの形式のリモートを読み込めるかは実機未検証のため、マージ前に 1 つ実際にアップロードして動作確認いただくのが安全です。

未対応(既存の lint エラー)

移行前のソースを git archive HEAD で取り出して検証し、移行前と件数・内容が完全に一致することを確認済みです。スコープ外として手を付けていません。

  • lint:tsc — CustomChatButton / CustomEntryPanel / CustomProfileModal の src/App.tsx でデモ用ハーネスが必須 props を渡していない(各 1 件)
  • lint:eslint — AdditionalToolbarButton 4 件(OverlayModal.tsx@ts-ignore / any)、他は no-unused-vars が各 1〜2 件。CustomChatButton は上記の型修正で 4 件 → 1 件に改善
  • lint:prettier — CustomChatButton / CustomEntryPanel / CustomMegaphoneButton / CustomProfileModal の既存ファイル

なお CustomOverlay/package.json にローカルで入っていた検証用の値(name: test-for-plugin-API-1725 / version: 1.0.0)は、テンプレートの既定値に戻した上でコミットしています。

🤖 Generated with Claude Code

CustomExitScreen was already Vite-based; this brings the remaining 10
templates in line with it so every template shares one build setup.

Per plugin:
- Replace webpack + @module-federation/enhanced with Vite 6 +
  @module-federation/vite, inlining configs/federationConfig.js into
  vite.config.ts
- Move public/index.html to a root index.html and replace the
  src/index.ts -> src/bootstrap.tsx async-boundary hack (a webpack MF
  requirement) with a plain src/main.tsx entry
- Convert scripts/{set_uuid,add_metadata,archive_dist}.js to ESM and
  switch uuidv4 -> uuid; set_uuid now also emits VITE_VERSION_ID
- Replace jest + ts-jest + babel with vitest, dropping the whole
  babel toolchain
- Drop src/types/declarations.d.ts in favour of vite/client types

Two things needed care to keep behaviour identical:

- CSS Modules were imported as `import * as styles`. webpack's
  css-loader v7 emits kebab-case named exports, so dynamic lookups like
  styles["status-recording"] and styles["urth-staff-red"] resolved.
  Vite only emits valid JS identifiers as named exports, so those keys
  would silently become undefined. All such imports are now default
  imports, with localsConvention "camelCase" keeping both key styles.
- webpack salted CSS class names with localIdentHashSalt: VERSION_ID so
  class names cannot collide with other plugins on the host. Vite has no
  equivalent option, so generateScopedName reproduces the same
  `[name]__[local]__[hash:base64:5]` naming with VERSION_ID in the hash.

Also removes the webpack-only `@import "~normalize.css"` in favour of a
plain `import "normalize.css"` from the component.

Fixes pre-existing type errors that were blocking Module Federation DTS
emit (Props typo in CustomChatModal, untyped tsparticles options,
querySelector element type, CSS-module computed keys, untyped
forwardRef in ToolbarButton.jsx).

Verified per plugin: build, unit tests, and browser rendering for
AdditionalToolbarButton, CustomOverlay and CustomWebCameraButton.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@kira924age kira924age self-assigned this Aug 10, 2026
kira924age and others added 2 commits August 10, 2026 16:30
- Ignore .mf/ and untrack the four committed
  .mf/diagnostics/latest.json build artifacts. They embedded absolute
  local paths and stale TYPE-001 records, and were rewritten on every
  build, so each template user picked up a spurious dirty file.
- Declare adm-zip in CustomEntryPanel. scripts/archive_dist.js imports
  it, but it only resolved via hoisting from @module-federation/vite ->
  dts-plugin, which would break under a strict node_modules layout.
- Throw when the root element is missing instead of silently skipping
  render. The pre-Vite entries failed loudly here; the guard turned an
  id mismatch between index.html and main.tsx into a blank page with a
  clean console.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
macOS generates these next to any browsed directory. The per-plugin
.gitignore files already cover them, but the root one did not, so
.DS_Store showed up as untracked on every status check.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@kira924age kira924age added dependencies Pull requests that update a dependency file setup labels Aug 10, 2026
@kira924age
kira924age merged commit 8326e75 into develop Aug 10, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file setup

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant