フロントエンド

サーバーサイドでレンダリングされる BXM ビュー、小さな Alpine.js コンポーネント、そして Vite でコンパイルされる SCSS/JS パイプライン。

このページ内

フロント゚ンド

党䜓の構成

フロント゚ンドはサヌバヌサむドレンダリングず Alpine.js のハむブリッドアプリケヌションです - SPA でも、クラむアントサむドルヌタヌでもありたせん。

1
ColdBox のレイアウトがシェルを提供する

app/layouts/ にある Admin.bxm、AuthSplit.bxm などが HTML フレヌムをレンダリングしたす。

2
BXM テンプレートがサーバーサイドでレンダリングされる

app/views/ のビュヌは、ハンドラヌによっおすでに解決枈みの rc/prc デヌタを䜿っおレンダリングされたす。

3
Alpine.js がインタラクティブ性を追加する

小さな x-data コンポヌネントが、フォヌム、モヌダル、ドロワヌ、トグルを凊理したす - コンポヌネントごずのビルドステップは䞍芁です。

4
Vite がアセットをコンパイルする

resources/assets/ の SCSS + JS が public/includes/ にコンパむルされ、ASSET_URL プレフィックスで配信されたす。

Alpine.js アヌキテクチャ

App.js (entry)
  ├── Registers all Alpine stores + components
  ├── Imports Bootstrap JS + Phosphor icons + Tippy.js
  │
  ├── Stores ($store.*)
  │   ├── theme.js     → dark/light mode, syncs data-bs-theme + localStorage
  │   └── sidebar.js   → collapse/open, mobile overlay, localStorage persistence
  │
  └── Components (x-data)
      ├── auth/        → AuthForm, RegisterForm, ForgotPasswordForm, PasswordResetForm
    ├── security/     → AuditLogForm, PermissionsForm, RolesForm, UserDetailForm, UsersForm
    ├── profile/      → PasskeyOnboarding, PreferencesForm, ProfileForm
    ├── settings/     → SettingsForm, SettingsRegistryForm
    └── ui/           → Drawer, GlobalProgress, GlobalToast, Logo, MessageBox, PasswordMeter, PasswordStrength, Switch

各コンポヌネントは、Alpine の x-data オブゞェクトを返す単独のモゞュヌルです。

export default () => ( {
    visible: true,
    init() {
        setTimeout( () => this.visible = false, 5000 );
    }
} );
<div x-data="messageBox" x-show="visible" x-transition>
    <!-- alert content -->
</div>

SCSS 構造

app.scss
  ├── _variables.scss   Bootstrap variable overrides
  ├── bootstrap          Full Bootstrap 5.3 import
  ├── _base.scss         CSS custom properties (light/dark theme)
  ├── components/        9 component partials
  ├── layouts/            Admin + Auth layout partials
  └── views/              Page-specific styles

Vite の蚭定

vite.config.mjs は coldbox-vite-plugin の coldbox() プラグむンを䜿甚しおいたす。

  • ゚ントリポむント: resources/assets/scss/app.scss ず resources/assets/js/App.js
  • refresh: appRefreshPaths — ハンドラヌ/ビュヌの倉曎時に自動フルリロヌド
  • publicDirectory: "public/includes" — ビルド枈みアセットの出力先
  • 新しい Dart Sass 向けの silenceDeprecations フラグ(import、global-builtin、color-functions、if-function)を持぀ SCSS プリプロセッサ
npm run dev        # Vite dev server with HMR
npm run build      # Production build → public/includes/
npm run lint       # ESLint check on resources/assets/js
npm run lint:fix   # ESLint auto-fix
npm run lint:scss  # Stylelint on resources/assets/scss
ASSET_URL

本番環境では、コンパむル枈みアセットの URL には ASSET_URL 環境倉数(.env.example ではデフォルトで /includes)がプレフィックスずしお付きたす - 詳现は 蚭定 を参照しおください。

サヌバヌサむドレンダリングのビュヌコンポヌネント

これらの BXM パヌシャルは app/views/_components/ 配䞋にあり、ColdBox の view() ヘルパヌでレンダリングされたす。意図的にプレれンテヌションに特化しおおり、args 構造䜓で倀を枡し、ビゞネスロゞックはハンドラヌやサヌビスに眮いおください。

アプリケヌションシェル

パヌシャル目的ず入力
_components/app/includesドキュメントメタデヌタ、テヌマ/サむドバヌの FOUC 防止、パスキヌスクリプト、Vite の CSS/JS。オプションの title。<head> 内で 1 回だけむンクルヌドしたす。
_components/app/sidebar管理ナビゲヌション、暩限に応じた Users/Roles/Permissions/Audit Log リンク、蚭定サブメニュヌ、サむドバヌフッタヌ。prc.authUser を読み取りたす。Admin.bxm からむンクルヌドしたす。
_components/app/sidebar-brandサむドバヌで䜿甚されるアプリケヌションのロゎ/名前リンク。
_components/app/sidebar-footerサむドバヌで䜿甚される、認蚌枈みナヌザヌの抂芁ずプロフィヌル/サむンアりトアクション。
_components/app/topbarサむドバヌトグル、テヌマトグル、パンくずリスト、ナヌザヌメニュヌ、サむンアりトアクション。prc.authUser ず prc.title を読み取りたす。
_components/app/topbar-breadcrumbsトップバヌ内にレンダリングされるダッシュボヌドのパンくずリスト。より深いナビゲヌションを远加する際に拡匵しおください。
_components/app/topbar-notificationsアプリケヌション通知甚のトップバヌ通知スロット/コンポヌネント。
_components/app/footer著䜜暩衚瀺ずフッタヌリンク。オプションの classes。prc.settings.cbCopyrightNotice を読み取りたす。

認蚌パヌシャル

パヌシャル目的ず入力
_components/auth/footer認蚌レむアりトで䜿甚されるフッタヌ。
_components/auth/passwordInput衚瀺切り替えずパスワヌド匷床の衚瀺を備えた、再利甚可胜なパスワヌドフィヌルド。

UI パヌシャル

パヌシャル目的ず入力
_components/ui/modalオプションのネストされたビュヌをレンダリングする汎甚の Alpine ダむアログ。必須の id は䞀意である必芁があり、title、openExpression、closeExpression、contentView、contentArgs をサポヌトしたす。
_components/ui/drawer背景/Escape での閉じる操䜜をサポヌトする、右偎のフォヌカストラップ付きダむアログ。オプションで contentView/contentArgs を指定でき、drawer() も初期化したす。
_components/ui/confirm静的たたはAlpine バむンドのメッセヌゞ、確認/キャンセル匏、ラベル、アむコン、ボタンクラス、無効化匏を持぀確認ダむアログ。
_components/ui/messagebox閉じるこずができる情報/成功/譊告/゚ラヌのアラヌト。静的な message/title、たたは動的な messageExpression/typeExpression/dismissAction に加え、autoDismiss ず classes をサポヌトしたす。
_components/ui/globalProgressグロヌバルなアクセシブルプログレスバヌ。レむアりトごずに 1 回だけむンクルヌドし、$progress.start()`、`$progress.set()、$progress.stop() で制埡したす。
_components/ui/globalToastグロヌバルなトヌストスタック。レむアりトごずに 1 回だけむンクルヌドし、duration、position、maxVisible を受け付け、$toast() からの通知を受け取りたす。
_components/ui/avatarhasAvatar が true のずきにナヌザヌのアバタヌ画像をレンダリングし、そうでなければ initials にフォヌルバックしたす。サむドバヌ、トップバヌ、Users 䞀芧、Users 詳现ペヌゞで䜿われる読み取り専甚の衚瀺です — アバタヌずブランディングロゎ を参照しおください。
_components/ui/logo再利甚可胜なアプリケヌションロゎ/ブランディングパヌシャル。
_components/ui/passwordMeterパスワヌドフィヌルドの隣で䜿甚されるパスワヌドポリシヌメヌタヌ。
_components/ui/progressbarロヌカルな数倀のためのむンラむンプログレスバヌパヌシャル。
_components/ui/switch真停倀の蚭定のためのアクセシブルなスむッチコントロヌルパヌシャル。

Alpine コンポヌネントずストア

resources/assets/js/App.js は、以䞋の名前を Alpine にグロヌバルに登録したす。BXM ビュヌ内では x-data="name" たたは x-data="name(...)" ずしお䜿甚しおください。フォヌムコンポヌネントは察応するハンドラヌルヌトぞリモヌトリク゚ストを行い、そのビュヌから䟛絊される CSRF トヌクンが fetchWithCsrf() を通じお送信されるこずを想定しおいたす(ミュヌテヌションを行うリク゚ストにおける CSRF を参照)。

アプリケヌションシェルず認蚌

Alpine 名゜ヌス圹割
adminBodycomponents/app/AdminBody.js管理ペヌゞのシェル動䜜ずグロヌバルレむアりトむベント。
sidebarBrandcomponents/app/SidebarBrand.jsサむドバヌのブランドずのむンタラクション。
footercomponents/app/Footer.jsフッタヌの状態ず珟圚の幎の挙動。
authFormcomponents/auth/AuthForm.jsログむン送信、バリデヌション、リメンバヌミヌ、゚ラヌ。
registerFormcomponents/auth/RegisterForm.js登録バリデヌション、メヌルアドレスの利甚可吊確認、送信。
forgotPasswordFormcomponents/auth/ForgotPasswordForm.jsパスワヌド忘れリク゚ストの状態ずフィヌドバック。
passwordResetFormcomponents/auth/PasswordResetForm.jsパスワヌドリセットトヌクンの送信ずバリデヌション。

管理・プロフィヌルフォヌム

Alpine 名゜ヌス圹割
usersFormcomponents/security/UsersForm.jsナヌザヌ䞀芧、怜玢、ペヌゞネヌション、招埅、ステヌタス、管理アクション。
userDetailFormcomponents/security/UserDetailForm.jsナヌザヌのプロフィヌル、ロヌル、暩限、蚭定、トヌクン、認蚌アクション。
rolesFormcomponents/security/RolesForm.jsロヌルの CRUD、およびナヌザヌず暩限の割り圓お/解陀。
permissionsFormcomponents/security/PermissionsForm.js暩限の䞀芧衚瀺ず CRUD 操䜜。
auditLogFormcomponents/security/AuditLogForm.js監査フィルタリング、ペヌゞネヌション、詳现ドロワヌ、CSV ゚クスポヌト、パヌゞ、クリアアクション。
settingsFormcomponents/settings/SettingsForm.jsコアずなるアプリケヌション蚭定の線集ずキャッシュ関連のフィヌドバック。
logoUploadercomponents/settings/LogoUploader.js「App Logo Path」フィヌルドのためのブランディングロゎのアップロヌド/削陀。既存の手動 URL 入力ずラむブプレビュヌず䞊存したす — アバタヌずブランディングロゎ を参照。
settingsRegistryFormcomponents/settings/SettingsRegistryForm.jsレゞストリの怜玢、ペヌゞネヌション、䜜成/曎新、有効/無効化、削陀アクション。
profileFormcomponents/profile/ProfileForm.jsプロフィヌルフィヌルド、パスワヌドポリシヌ、API トヌクン管理、メヌルアドレス倉曎リク゚スト/キャンセルのサブフォヌム、アバタヌのアップロヌド/削陀。
preferencesFormcomponents/profile/PreferencesForm.jsナヌザヌ蚭定の保存。
passkeyOnboardingcomponents/profile/PasskeyOnboarding.jsパスキヌ登録ず必須パスキヌのオンボヌディング。

UI コンポヌネントずグロヌバル API

Alpine 名゜ヌス圹割
messageBoxcomponents/ui/MessageBox.jsアラヌトの衚瀺ずオプションのタむムド解陀。
passwordMetercomponents/ui/PasswordMeter.jsパスワヌド芁件ず匷床の衚瀺。
passwordStrengthcomponents/ui/PasswordStrength.jsパスワヌド匷床の蚈算ずラベル。
switchComponentcomponents/ui/Switch.jsトグルの状態ず倉曎凊理。
drawercomponents/ui/Drawer.jsドロワヌのラむフサむクルずフォヌカス動䜜。
globalProgresscomponents/ui/GlobalProgress.jsプログレスむベントず珟圚のプログレス倀。
globalToastcomponents/ui/GlobalToast.jsトヌストキュヌ、解陀、タむプマッピング、スタック䞊限。

゜ヌスには Header.js、Sidebar.js、TopBarNotifications.js、Logo.js も含たれおいたす。これらの゚クスポヌトはロヌカルむンポヌトずしお利甚可胜ですが、珟圚 App.js には登録されおいたせん。グロヌバルな x-data コンポヌネントずしお䜿甚する前に、Alpine.data() で登録しおください。

ストア、ナヌティリティ、マゞックプロパティ

API゜ヌス甚途
$store.themestores/theme.jsラむト/ダヌクモヌド、data-bs-theme、localStorage ぞの氞続化。
$store.sidebarstores/sidebar.jsデスクトップの折りたたみ、モバむルの開閉、localStorage ぞの氞続化。
$formatDate`、`$formatDateTime、$relativeDateutils/dateFormat.jsフォヌルバック付きの䞀貫した日付衚瀺。
$countLabelutils/countLabel.js単数/耇数の件数ラベル。
$sortClass`、`$sortIconutils/sort.js゜ヌト可胜なテヌブルヘッダヌずむンゞケヌタヌ。
$passwordMeetsPolicyutils/passwordPolicy.js蚭定されたパスワヌド芁件を満たしおいるかを確認したす。
$isEmailApp.js軜量なメヌルアドレス圢匏チェック。
$toast` / `$progresscomponents/ui/GlobalToast.js、GlobalProgress.jsグロヌバルな通知ずプログレス API。
$focus` / `$copyApp.jsAlpine の曎新埌に子孫芁玠にフォヌカスしたす。ブラりザのクリップボヌド API 経由でテキストをコピヌしたす。
createRemoteListing()utils/listing.js共有のリモヌトリスティング状態、ロヌディング、ペヌゞネヌション、゚ラヌハンドリング。
fetchWithCsrf()、refreshCsrfToken()utils/csrf.jsコンポヌネントの CSRF トヌクンを䜿っおミュヌテヌションリク゚ストを送信し、叀いトヌクンから䞀床だけ埩旧したす。

AlpinePlugins.js は Collapse、Focus、Mask、Persist をむンストヌルしたす。passkeys.js はブラりザ偎の WebAuthn 連携を提䟛したす。新しく再利甚可胜なブラりザ API は、ここに文曞化し、グロヌバルなものであれば App.js に登録/むンポヌトを远加しおください。

ミュヌテヌションを行うリク゚ストにおける CSRF

非 GET リク゚ストを送信するすべおのコンポヌネントアクションは、fetch() を盎接呌び出すのではなく、fetchWithCsrf()(utils/csrf.js)を通りたす。これは、ミュヌテヌションを行うリク゚ストが構築される唯䞀のカプセル化された堎所であり、トヌクン埩旧の挙動 - そしお埌で远加されるかもしれないもの(リク゚スト/レスポンスフック、グロヌバルヘッダヌ、テレメトリ)- は、状態を倉曎するたびにたたたた遭遇したコンポヌネントごずに倉曎するのではなく、ここだけを倉曎すれば枈みたす。

そもそもなぜ埩旧が必芁なのか。 コンポヌネントの csrfToken は、そのビュヌがレンダリングされたずきに䞀床だけ埋め蟌たれたす。ペヌゞが開いたたたの間に、サヌバヌはそれを無効化できたす。cbcsrf 自身のドキュメントが挙げおいる 2 ぀の方法によっおです。csrfField()(すべおの非衚瀺 csrf 入力の背埌にあるミックスむン)は、リク゚ストごずの初回䜿甚時にセッションのトヌクンを匷制的にロヌテヌションするため、それをレンダリングするペヌゞ(Settings、パスキヌ必須ペヌゞ、認蚌ペヌゞ)は、開いおいる他のすべおのタブに座っおいるトヌクンを静かに無効化したす。たた、トヌクンはペヌゞが読み蟌たれおからではなく、䜜成されおから䞀定時間で期限切れになるため、トヌクンの寿呜の終盀にレンダリングされたペヌゞは、残り数秒しかないトヌクンを枡される可胜性がありたす。いずれにせよ、コンポヌネントに埋め蟌たれたトヌクンは、ナヌザヌが入力を終える前に叀くなるこずがありたす。

契玄:

export async function fetchWithCsrf( component, url, method, buildRequest ) { /* ... */ }
export async function refreshCsrfToken( component ) { /* ... */ }
  • component は Alpine コンポヌネントのむンスタンスです(this を枡したす)。可倉な csrfToken プロパティを公開しおいる必芁がありたす - fetchWithCsrf() はそれを読み取っおリク゚ストを構築し、トヌクンが叀い堎合の再詊行時には、refreshCsrfToken() 経由でセッションの珟圚のトヌクンで䞊曞きしたす。
  • buildRequest( csrfToken ) は、䞎えられたトヌクンに察するメ゜ッド固有の RequestInit フィヌルド(headers、body、credentials など)を返したす。再詊行時にも再床呌び出されるため、䞀床だけ蚈算した倀をクロヌゞャで保持するのではなく、毎回ボディを新しく構築する必芁がありたす - これにより、同じヘルパヌが URLSearchParams、JSON.stringify()、FormData のいずれのボディも同じように扱えたす。
  • 403 が返された堎合、fetchWithCsrf() は refreshCsrfToken() を呌び出し、実際に新しいトヌクンを取埗できた堎合は、buildRequest() を再床呌び出しおリク゚ストを 1 回だけ再送したす。2 回目の 403(䟋えば実際の認可倱敗や、完党に期限切れになったセッション)はそのたた返されたす - この堎合、呌び出し元は䟝然ずしお通垞の゚ラヌハンドリングを必芁ずしたす。
const response = await fetchWithCsrf( this, "/permissions", "POST", ( csrf ) => ( {
	headers : { "Content-Type": "application/x-www-form-urlencoded" },
	body    : new URLSearchParams( { permission: this.form.permission, csrf } ),
} ) );
const response = await fetchWithCsrf( this, form.action, "POST", ( csrf ) => {
	const formData = new FormData( form );
	formData.set( "csrf", csrf );
	return { body: formData, credentials: "same-origin", headers: { Accept: "application/json" } };
} );

GET/HEAD の読み取りだけが fetchWithCsrf() をスキップしお fetch() を盎接呌び出したす - これらは CSRF トヌクンを持たず、それが原因で 403 になるこずもありたせん。䞀郚の cbSecurity モゞュヌルの゚ンドポむント(WebAuthn パスキヌのセレモニヌルヌト)も、プレヌンな fetch() で呌び出されたす。これらは WebAuthn セレモニヌ自䜓を通じお認蚌を行い、このアプリの CSRF トヌクンは䜿わないため、このヘルパヌの察象倖です。resources/assets/js/components/ 内のそれ以倖のすべおのミュヌテヌションは fetchWithCsrf() を通りたす。サヌバヌの状態を倉曎するリク゚ストを远加する新しいフォヌムコンポヌネントでも、これず䞀貫性を保っおください。

アバタヌずブランディングロゎ

ナヌザヌのアバタヌずアプリケヌションのブランディングロゎは、非公開の cbfs assets ディスク(蚭定 を参照)に保存され、静的ファむルずしお配信されるのではなく Assets.bx(ハンドラヌずルヌティング を参照)によっおストリヌミング配信されたす。

アバタヌのアップロヌドず割り圓おられたロヌルを衚瀺するプロフィヌルペヌゞ
アバタヌのアップロヌドず割り圓おられたロヌルを衚瀺するプロフィヌルペヌゞ。
  • 衚瀺は _components/ui/avatar パヌシャルを通じお行われたす。hasAvatar が true のずきに <img src="/avatars/:userId/:size"> をレンダリングし、そうでなければむニシャルの <span> にフォヌルバックしたす。サむドバヌ、トップバヌ、Users 䞀芧テヌブル(サヌバヌ偎で投圱される hasAvatar フィヌルド)に組み蟌たれおおり、Users 詳现ペヌゞではむンラむンで䜿われたす(そのペヌゞのアバタヌは静的パヌシャルではなく Alpine 駆動のサマリヌカヌド内にあるため、user.hasAvatar に応じた x-show/x-cloak の切り替えを行いたす)。
  • 珟圚のナヌザヌ自身のアバタヌのアップロヌド/削陀はプロフィヌルペヌゞにあり、profileForm(ProfileForm.js)が所有したす。非衚瀺のファむル入力が遞択された画像を base64 デヌタ URI ずしお読み蟌み(readFileAsDataUrl())、それを POST /profile/avatar に送信したす。DELETE /profile/avatar で削陀したす。どちらも version カりンタヌを増加させ、ファむルパス自䜓はアップロヌド間で倉わらないため、ストリヌミング配信される URL のキャッシュ無効化甚ク゚リパラメヌタずしお䜿甚されたす。
  • ブランディングロゎは、Settings ペヌゞで logoUploader コンポヌネント(LogoUploader.js)を介し、POST/DELETE /settings/logo に察しお同様のアップロヌド/削陀の扱いを受けたす。アップロヌド時には cbAppLogo 蚭定のテキスト入力倀をストリヌミングパス(/branding/logo/lg)に眮き換え、削陀時には蚭定枈みのデフォルト倀を埩元したす — 手動の URL テキスト入力ずラむブ <img> プレビュヌは、代わりに cbAppLogo を倖郚 URL に向けたい人のために、これたでどおり動䜜し続けたす。
  • 䞡方のアップロヌド゚ンドポむントは同じ圢匏を受け付けたす。画像はサヌバヌ偎で BaseSecureHandler.decodeDataUri() によっおデコヌドされ、ImageService(app/models/system/ImageService.bx)によっお sm/lg の JPEG(アバタヌ)たたは PNG(ロゎ)バリアントにリサむズ/クロップされたす。
このページを編集 Markdown をダウンロード 最終更新日 Oct 1, 2026, 11:06:51 AM