この記事はバージョン Winter ’26 において執筆しています。
現在の動作と異なる場合がありますので、ご認識おきください。
LWC (Lightning Web Components) を開発する際、私たちはつい HTML や JavaScript のロジックに集中しがちです。 しかし、Experience Cloud 用のコンポーネントにおいて、最も時間をかけるべきファイルは js-meta.xml かもしれません。
なぜなら、このファイルの記述次第で、そのコンポーネントが「ただ動くだけの部品」になるか、「システム管理者がビルダー上で自由にカスタマイズできる柔軟な部品」になるかが決まるからです。
「タイトルを変えるたびにコード修正依頼が来る」 そんな不毛な運用を避けるために、今回は js-meta.xml を使い倒して、設定値をプロパティパネルに外出しする技術を解説します。
基本:Experience Cloud で使えるようにする
まず、開発したLWCをエクスペリエンスビルダーのコンポーネント一覧(左側のメニュー)に表示させるための最低限の設定です。 targets に lightning__CommunityPage を指定します。
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>65.0</apiVersion>
<isExposed>true</isExposed>
<masterLabel>カスタムお知らせバナー</masterLabel>
<description>お知らせを表示するバナーです。テキストと背景色を変更可能です。</description>
<targets>
<target>lightningCommunity__Page</target>
<target>lightningCommunity__Default</target>
</targets>
</LightningComponentBundle>
核心:プロパティ(変数)を公開する
ここからが本題です。 JavaScript内で @api title; のように宣言した変数を、ビルダーの画面右側(プロパティパネル)から入力可能にします。
これには targetConfigs を使用します。先ほどの js-meta.xml を以下のように編集します。
実装例:タイトルと表示件数、フラグを設定可能にする
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>65.0</apiVersion>
<isExposed>true</isExposed>
<masterLabel>カスタムお知らせバナー</masterLabel>
<description>テキスト、表示件数、色を変更可能なお知らせバナーです。</description>
<targets>
<target>lightningCommunity__Page</target>
<target>lightningCommunity__Default</target>
</targets>
<targetConfigs>
<targetConfig targets="lightningCommunity__Default">
<property
name="bannerTitle"
type="String"
label="バナータイトル"
default="重要なお知らせ" />
<property
name="maxItems"
type="Integer"
label="最大表示件数"
default="5" min="1" max="10" />
<property
name="showIcon"
type="Boolean"
label="アイコンを表示する"
default="true" />
<property
name="themeColor"
type="String"
label="テーマカラー"
datasource="Blue, Red, Green, Gray"
default="Blue" />
</targetConfig>
</targetConfigs>
</LightningComponentBundle>
このように記述することで、管理者はコードを触ることなく「タイトル」や「色」を変更できるようになります。
変数名の命名規則
js-meta.xml の name 属性はキャメルケース(bannerTitle)で記述します。ケバブケース(banner-title)などは使用できないため注意してください。
JavaScript 側での受け取り方
メタデータ側で定義したプロパティは、JavaScript ファイル (.js) 側では通常の @api デコレータが付いたプロパティとして受け取ります。
html / js / css のサンプルを記載しておきます。
customNotificationBanner.html
<template>
<div class={bannerClass}>
<template lwc:if={showIcon}>
<lightning-icon
icon-name="utility:info"
alternative-text="Info"
size="small"
class="slds-m-right_small">
</lightning-icon>
</template>
<h2 class="slds-text-heading_medium">{bannerTitle}</h2>
<p class="slds-m-left_small">
最大表示件数: {maxItems} 件
</p>
</div>
</template>
customNotificationBanner.js
import { LightningElement, api } from 'lwc';
export default class CustomNotificationBanner extends LightningElement {
@api bannerTitle;
@api maxItems;
@api showIcon;
@api themeColor;
get bannerClass() {
// ベースのSLDSクラス + テーマ用クラス + レイアウト用独自クラス
return `slds-box slds-theme_alert-texture theme-${this.themeColor.toLowerCase()} banner-layout`;
}
}
customNotificationBanner.css
/* テーマカラーごとのスタイル定義 */
.theme-blue {
background-color: #cce5ff;
color: #004085;
border-color: #b8daff;
}
.theme-red {
background-color: #f8d7da;
color: #721c24;
border-color: #f5c6cb;
}
.theme-green {
background-color: #d4edda;
color: #155724;
border-color: #c3e6cb;
}
.theme-gray {
background-color: #e2e3e5;
color: #383d41;
border-color: #d6d8db;
}
/* コンポーネント全体の調整 */
.banner-layout {
display: flex;
align-items: center;
}
設置例

【LWR】CMSコンテンツを選択させる裏技
LWRサイトで特に強力なのが、Salesforce CMS のコンテンツ(画像やニュース) をビルダー上で選択させる機能です。 これは ContentReference という特殊な型を使用します。
<property
name="contentId"
type="ContentReference"
label="表示するCMSコンテンツ"
description="Salesforce CMSから画像やニュースを選択してください。"
/>
これを設定すると、プロパティパネルに「コンテンツを選択」ボタンが現れ、管理者はCMSワークスペースから直接コンテンツを紐付けることができます。 取得した contentId を使って、LWC側でコンテンツの詳細情報を取得・表示することが可能になります。
参考までに、 ContentReference を使用したサンプルコンポーネントのソースコードを記載します。(※やっていることは標準の画像コンポーネントと同じです)

cmsImageDisplay.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>62.0</apiVersion>
<isExposed>true</isExposed>
<masterLabel>CMS画像表示</masterLabel>
<description>CMSから選択した画像を表示します。</description>
<targets>
<target>lightningCommunity__Page</target>
<target>lightningCommunity__Default</target>
</targets>
<targetConfigs>
<targetConfig targets="lightningCommunity__Default">
<property
name="contentKey"
type="ContentReference"
label="画像を選択"
description="表示したいCMS画像を選択してください。"
filter="cms_image"
/>
</targetConfig>
</targetConfigs>
</LightningComponentBundle>
cmsImageDisplay.html
<template>
<div class="cms-image-container">
<template lwc:if={hasImage}>
<img src={imageUrl} alt={altText} class="responsive-image" />
</template>
<template lwc:else>
<div class="placeholder slds-box slds-theme_shade slds-text-align_center">
<p>ビルダーのプロパティから画像を選択してください</p>
</div>
</template>
</div>
</template>
cmsImageDisplay.js
import { LightningElement, api, wire } from 'lwc';
// 拡張CMSのコンテンツを取得するためのモジュール
import { getContent } from 'experience/cmsDeliveryApi';
import siteId from '@salesforce/site/Id';
import basePath from '@salesforce/community/basePath';
export default class CmsImageDisplay extends LightningElement {
/**
* js-meta.xml から渡されるコンテンツキー(ID)
* ビルダーで選択されたコンテンツのユニークなキーが入ります
*/
@api contentKey;
imageUrl;
altText;
errorMessage;
/**
* コンテンツキーを使って、CMSから詳細データを取得
*/
@wire(getContent, {
channelOrSiteId: siteId,
contentKeyOrId: '$contentKey'
})
wiredContent({ error, data }) {
if (data) {
try {
// getContent は単一のコンテンツオブジェクトを返す
const content = data;
if (content && content.contentBody) {
const body = content.contentBody;
// sfdc_cms__image (画像) コンテンツタイプの場合
if (body['sfdc_cms:media']) {
let url = body['sfdc_cms:media'].url;
// URLが相対パスの場合、サイトのベースパスと /sfsites/c を付与
if (url && url.startsWith('/') && basePath) {
// basePathが '/' で終わっている場合と url が '/' で始まっている場合の重複を避ける
const cleanBasePath = basePath.endsWith('/') ? basePath.slice(0, -1) : basePath;
url = `${cleanBasePath}/sfsites/c${url}`;
}
this.imageUrl = url;
this.altText = content.title; // 代替テキストとしてタイトルを使用
this.errorMessage = undefined;
}
}
} catch (e) {
console.error('CMSデータの解析に失敗しました', e);
}
} else if (error) {
this.errorMessage = '画像の読み込みに失敗しました。';
console.error('CMS Error:', error);
}
}
/**
* 画像が正しく取得できたか判定するゲッター
*/
get hasImage() {
return this.imageUrl != null;
}
}
cmsImageDisplay.css
.cms-image-container {
width: 100%;
display: flex;
justify-content: center;
}
.responsive-image {
max-width: 100%;
height: auto;
border-radius: 4px; /* 任意:角丸 */
display: block;
}
.placeholder {
width: 100%;
padding: 2rem;
color: #706e6b;
}
まとめ:変更に強いコンポーネントを作ろう
LWC開発者の腕の見せ所は、複雑なロジックを書くことだけではありません。 「明日、要件が変わってもコードを修正しなくて済む設計」 をすることこそが、プロフェッショナルな仕事です。
- 固定の文字列は
Stringプロパティにする。 - 表示制御の条件は
Booleanプロパティにする。 - スタイルは
Select(データソース)で選ばせる。
js-meta.xml を活用して、システム管理者(未来の自分)に優しいコンポーネント開発を心がけましょう。
参考URL
Experience Cloud 用コンポーネント設定 (js-meta.xml)
XML設定ファイルの要素(ContentReference 型の仕様含む)
CMS配信API (experience/cmsDeliveryApi > getContent)



読者の声