The end-to-end pattern is: define the channel, deploy the metadata, publish from one component, subscribe in another.
- Define the Message Channel
Create force-app/main/default/messageChannels/MyChannel.messageChannel-meta.xml with the lightningMessageChannel type, masterLabel, isExposed, and lightningMessageFields.
- Deploy the channel
Use the Salesforce CLI: sf project deploy start to push the channel definition to the org.
- Publish from a component
In the publisher LWC: import {publish, MessageContext} from ''lightning/messageService''; import MY_CHANNEL from ''@salesforce/messageChannel/MyChannel__c''. Call publish(this.messageContext, MY_CHANNEL, payload).
- Subscribe in another component
In the subscriber LWC: import {subscribe, MessageContext} from ''lightning/messageService''. Call subscribe(this.messageContext, MY_CHANNEL, handlerFn) in connectedCallback.
- Unsubscribe in disconnectedCallback
Clean up the subscription in disconnectedCallback to prevent memory leaks: unsubscribe(this.subscription).
- Test on a Lightning Page
Place both components on the same Lightning Page via App Builder. Verify the publisher and subscriber communicate as expected.
The XML metadata declaring the channel.
The LWC that calls publish.
The LWC that calls subscribe and handles messages.
The injected @wire context required for both publish and subscribe.
Required in disconnectedCallback to prevent leaks.
- Subscriptions must be cleaned up in disconnectedCallback. Without cleanup, the components leak references and accumulate handlers.
- Messages do not cross page boundaries. Navigating to a new record breaks the subscriptions; design accordingly.
- The isExposed flag controls cross-namespace visibility. Set to true to allow other packages to publish or subscribe to the channel.
- Performance can degrade with high message frequency. Throttle or debounce publishers when upstream sources produce fast updates.