LEARNING OBJECTIVES โต
- Understand the challenges of scale when distributing HTML/Web Components across hundreds of autonomous engineering teams.
- Implement strict Component Contract Testing to prevent regression in HTML attributes, slots, and event signatures.
- Design tree-shakeable, modular Web Component packaging strategies for enterprise monorepos.
- Master Semantic Versioning (SemVer) and automated contract gating for design systems and shared UI registries.
๐ The Mental Model & Story (Intuitive Foundation)
Imagine an international electric plug and socket standard (like the Type-C European or Type-B North American power plug).
Millions of manufacturers build thousands of different electronic appliancesโhairdryers, laptops, refrigerators, televisionsโand billions of homes install wall outlets. If the standards committee suddenly decided on a Tuesday to move the two prongs 3 millimeters closer together without warning, billions of devices around the world would instantly stop working. Power grids would throw errors, and consumers would be furious.
RIGID HARDWARE INTERFACE CONTRACT:
[Wall Socket (Host HTML)] <==== Strictly Defined Contract (Prong Width/Voltage) ====> [Appliance (Component)]
At FAANG scale (Meta, Google, Apple, Netflix, Amazon), a single core UI library is consumed by 2,000+ engineers across 400 different web applications, internal tools, and customer portals.
If a design system engineer renames an HTML attribute on a custom element from <user-card user-id="..."> to <user-card account-id="...">, or deletes a named <slot name="badge">, that single breaking change can silently break production checkout flows or data dashboards across dozens of unrelated teams.
To scale reliably, enterprise organizations treat their HTML Component interfaces as Strict Hardware Contracts. We define immutable attribute schemas, enforce automated contract verification tests in CI, and package components so that unused HTML templates and styles are completely tree-shaken out of production bundles.
Technical Deep Dive & Specifications
The Monorepo Component Lifecycle
In large enterprise monorepos (managed with Turborepo, Nx, or Bazel), components follow a strictly disciplined lifecycle:
+---------------------------------------------------------------------------------------+
| ENTERPRISE MONOREPO PACKAGING PIPELINE |
+---------------------------------------------------------------------------------------+
| |
| 1. AUTHORING (/packages/ui-components/src/button.ts) |
| - Typescript Custom Element + JSDoc Custom Element Manifest annotations |
| - Declarative Shadow DOM template + Scoped CSS Tokens |
| |
| โ |
| โผ |
| 2. CONTRACT EXTRACTION (Custom Elements Manifest Analyzer) |
| - Automatically generates custom-elements.json (Public Schema Contract) |
| - Validates: Attributes, Properties, Slots, CSS Parts, Custom Events |
| |
| โ |
| โผ |
| 3. CI CONTRACT GATING (Semantic Versioning Linter) |
| - Diffs new custom-elements.json against previous git tag |
| - Attribute deleted or renamed? -> BLOCK PR! Require Major Version Bump (2.0.0) |
| |
| โ |
| โผ |
| 4. SIDE-EFFECT-FREE PACKAGING (/packages/ui-components/dist/...) |
| - "sideEffects": false in package.json |
| - Exports granular entry points: import '@faang/ui/button' (Zero unused code) |
+---------------------------------------------------------------------------------------+
Custom Elements Manifest (CEM) Schema Contract
The Custom Elements Manifest is the official open standard JSON format describing the complete public interface of Web Components. It allows automated tools, IDEs, and linters to verify compliance:
{
"schemaVersion": "1.0.0",
"readme": "",
"modules": [
{
"kind": "javascript-module",
"path": "src/components/user-badge.js",
"declarations": [
{
"kind": "class",
"name": "UserBadge",
"tagName": "faang-user-badge",
"attributes": [
{ "name": "user-id", "type": { "text": "string" }, "required": true },
{ "name": "variant", "type": { "text": "'solid' | 'outline'" }, "default": "'solid'" }
],
"slots": [
{ "name": "", "description": "Default user display label" },
{ "name": "avatar", "description": "Optional profile picture slot" }
],
"events": [
{ "name": "badge:click", "type": { "text": "CustomEvent<{ userId: string }>" } }
]
}
]
}
]
}
Contract Compatibility Matrix (SemVer Rules)
| Component Change | Interface Impact | Required SemVer Bump | CI Action |
|---|---|---|---|
Adding a new optional attribute (size="sm") |
Backward-compatible addition | MINOR (1.1.0) | Passes contract check |
Adding a new named slot (<slot name="icon">) |
Backward-compatible addition | MINOR (1.1.0) | Passes contract check |
Renaming/Deleting an attribute (user-id -> uid) |
Breaking Change! | MAJOR (2.0.0) | Fails CI if minor/patch |
Removing a slot (<slot name="avatar">) |
Breaking Change! (Consuming markup rendered invisible) | MAJOR (2.0.0) | Fails CI if minor/patch |
| Fixing an internal CSS layout bug | No public interface mutation | PATCH (1.0.1) | Passes contract check |
๐ป Interactive Code Playground
Below is a complete, browser-runnable Component Contract Testing & Gating Harness. It simulates an automated CI test suite that verifies whether a custom element complies with its public interface contract (attributes, slots, and event dispatch).
Starter Code
Line-by-Line Code Breakdown
- Lines 75โ124 (
FaangUserChipComponent): Encapsulated production Web Component implementing the strict public contract. It definesobservedAttributes, default slot fallbacks, and composed custom event dispatching. - Lines 130โ136 (
CONTRACT_SCHEMA): The authoritative JSON interface contract. In enterprise monorepos, this schema is generated from source code and compared against production releases during CI builds. - Lines 145โ172 (
runContractTests): The automated gating suite. It verifies:- Element registration status.
- Observed attribute reactivity.
- Slot layout integrity (preventing silent UI breakage).
- Event dispatch payload signatures and boundary traversal (
composed: true).
Expected Browser Render Output
Enterprise Component Contract Gating
------------------------------------------------------------------------
[Live Component Under Test]
โ ๐ค Alexandra Chen (EMP-9021)
[Execute CI Contract Suite] (Clicking button triggers assertions):
--- INITIATING CONTRACT ASSERTIONS ---
โ PASS: Custom element <faang-user-chip> is registered in window.customElements
โ PASS: Component observes required contract attributes [user-id]
โ PASS: Component defines all contract slots [default, avatar]
โ PASS: Component dispatches 'chip:select' with valid payload { userId }
--- CONTRACT SUITE COMPLETE: 0 BREAKING CHANGES DETECTED ---๐๏ธ Hands-On Exercise
๐ฏ The Challenge: Build an Automated Breaking Change Detector
Instructions:
- Write a JavaScript utility
detectBreakingChanges(oldContract, newContract)that takes two Custom Element Manifest schemas. - The function must detect and report:
- Any deleted attributes (Breaking change -> Fail).
- Any deleted named slots (Breaking change -> Fail).
- Any renamed custom events (Breaking change -> Fail).
- If breaking changes are found, return
{ compatible: false, breakingErrors: [...] }. Otherwise, return{ compatible: true }.
๐ Starter Code Sandbox
โ ๏ธ Common Pitfalls
- Barrel-File Export Bloat (
index.js): Exporting 200 components from a singleindex.jsfile (import { Button, Table, Modal } from '@company/ui') often forces bundlers to include all 200 component classes in the client payload. Use subpath exports inpackage.json(@company/ui/button). - Silent Property vs Attribute Disconnect: Updating a JavaScript property
element.userId = '123'without reflecting it back to the HTML attribute (this.setAttribute('user-id', ...)), or vice versa, causes DOM debugging confusion and breaks CSS attribute selectors ([user-id]). - Mutating Slot Content Directly from Shadow DOM: A Web Component should never modify or delete elements placed in its
<slot>by the consumer. Use<slot>purely for layout projection.
๐ก Pro Tips
- Annotate with Custom Elements Manifest (CEM): Add standard JSDoc tags (
@customElement,@attr,@slot,@event) above your component class to automatically generate documentation, TypeScript types, and Storybook controls with zero manual maintenance. - Configure
"sideEffects": false: Ensure your design system package sets"sideEffects": ["**/*.css"]inpackage.jsonso webpack and Rollup can aggressively tree-shake unreferenced component classes.
๐ Key Takeaways
- At enterprise scale, HTML Component Interfaces are Hardware Contracts requiring strict backward compatibility.
- The Custom Elements Manifest (CEM) standardizes the machine-readable schema for Web Components.
- Renaming an attribute, deleting a slot, or altering an event signature requires a Major SemVer bump (2.0.0).
- Monorepos should package components with subpath exports to guarantee tree-shakeable client bundles.
- CI/CD pipelines should run automated contract verification suites to catch breaking changes before deployment.
- --