Component Architecture
Each component handles one UI role or feature (SRP enforced)
Inputs (@api
) are readonly and sanitized
Component hierarchy depth ≤ 3, slots used for composition
Shadow DOM usage is considered for style encapsulation (if using native shadow)
Reactivity & Data Flow
Avoid unnecessary @track
– only use when mutating nested structures
Use Object.freeze()
for immutable inputs
Prefer getter
logic over template inline ternaries
@api
properties are never mutated internally (unidirectional data flow)
Avoid computed getter dependencies on non-tracked/non-reactive state
Lifecycle Control
connectedCallback()
is used for setup logic only—no UI code
renderedCallback()
guarded with this.hasRendered = true
Cleanup logic (e.g. event listeners, timers) in disconnectedCallback()
jsCopyEditdisconnectedCallback() {
clearInterval(this.refreshTimer);
}
List Rendering
Use for:each
with key={uniqueId}
for all dynamic lists
Avoid nested iterations—flatten data in JS if needed
Use virtual scrolling or pagination for large datasets
Apex Integration (Wire & Imperative)
@wire
with cacheable=true
for read-only, reactive fetches
Imperative Apex used only for button-driven actions
Use try/catch
+ error handler for all imperative calls
Apex errors bubble via CustomEvent('error', detail)
Avoid JSON.stringify()
/parse()
for Apex serialization unless required
Validate Apex input shapes before sending (avoid undefined/nulls)
Event & State Management
Use CustomEvent
with composed: true, bubbles: true
for cross-DOM events
Maintain global pub/sub pattern (if needed) in a shared utility module
Avoid storing state in the DOM; use tracked vars, not dataset
Security & Locker Compliance
No direct access to window
, document
– use guarded wrappers
External scripts only loaded via loadScript()
+ allowlist in CSP
Use DOMPurify
or input filters before injecting into innerHTML (if applicable)
Follow Locker-compliant style scoping (no global selectors)
UI Rendering Efficiency
lwc:if
used for branching logic over if:true
Expensive render paths split with requestAnimationFrame()
or setTimeout()
DOM queries (querySelector
, querySelectorAll
) cached in memory
Styles use SLDS utility classes; no hardcoded px values unless scoped
Debugging & Monitoring
LWC Inspector used to monitor property changes & component tree
Chrome DevTools → Performance tab used to profile slow renders
All external API calls wrapped with timers for benchmarking
CPU-heavy logic timed and pushed to logs in debug builds
Testing & Automation
Jest unit tests mock wire + simulate user events (fireEvent
)
All imperative Apex functions covered with jest.fn()
createElement()
used for DOM-level testing in Jest
Integration tests confirm data flow across @api
boundaries
Refresh & Navigation
Record/field updates use LDS wire & getRecordNotifyChange()
Navigation handled via NavigationMixin.Navigate()
or PageReferenceUtils
No full page reloads or window.location.href
usage
Governor Limit Handling (Server-Side Awareness)
Apex logs reviewed for SOQL, CPU, Heap, DML stats
Lists passed to Apex are size-checked (records.length < 200
)
SOQL queries outside of loops, batched server logic
Final Technical Validation Checklist
Category Checked ✅ Lifecycle Hooks Guarded ✔️ DOM Access Cached ✔️ Apex Inputs Validated ✔️ Event Propagation Controlled ✔️ Shadow DOM Compliant ✔️ Jest Tests Written ✔️ External Scripts Deferred ✔️ LWC Inspector Profiling Done ✔️