Key takeaways
- Use Lightning Data Service and base components before writing custom Apex and markup.
- Prefer cacheable wired Apex for reads and imperative calls for actions the user triggers.
- Design small, composable components that communicate through public properties and events.
- Test components with Jest and Apex with unit tests, and respect field-level security in every query.
Lightning Web Components (LWC) is Salesforce’s modern UI framework, built on web standards such as custom elements, modules and shadow DOM. It makes it possible to build fast, polished interfaces inside Salesforce, but without discipline, components quickly become hard to change. These are the practices we follow on client projects.
Start with what Salesforce already gives you
- Base components such as
lightning-record-form,lightning-datatableandlightning-inputhandle accessibility, styling and validation for you. - Lightning Data Service through wire adapters like
getRecordreads and caches records, respects sharing and field-level security, and keeps components in sync when data changes. - Salesforce Lightning Design System classes keep custom markup consistent with the rest of the org.
Wire or imperative Apex?
| Use | Approach |
|---|---|
| Reading data that can be cached | Wire an Apex method annotated @AuraEnabled(cacheable=true) |
| Actions triggered by a user, such as save or submit | Call Apex imperatively and handle the promise |
| Standard record reads and updates | Lightning Data Service and updateRecord, no Apex needed |
After changing data with imperative Apex, use refreshApex or notify Lightning Data Service so other components show current values.
Design components to compose
- Keep each component focused on one job, such as a filter bar, a results table or a detail panel.
- Pass data down with public
@apiproperties and send changes up with custom events. - Use Lightning Message Service for communication between unrelated components on the same page.
- Avoid reaching into child components’ internals; expose public methods deliberately when needed.
Performance
- Query only the fields and rows the component needs, with sensible limits and server-side filtering.
- Load heavy data lazily, for example when a tab is opened or a user scrolls.
- Debounce search inputs so each keystroke does not call the server.
- Use getters for derived values instead of recalculating in templates.
Security
- In Apex controllers, enforce sharing with
with sharingand respect field and object permissions, for example usingWITH USER_MODEorSecurity.stripInaccessible. - Never trust input from the component; validate on the server.
- Use base components and avoid inserting raw HTML, which reduces cross-site scripting risks.
Testing and maintenance
- Write Jest tests for component logic with the Salesforce LWC Jest tooling, mocking wire adapters and Apex calls.
- Keep Apex unit tests meaningful, asserting behavior rather than chasing coverage.
- Store components in source control and deploy through a pipeline, not by hand.
- Document public properties and events at the top of each component.
Well-built components are the difference between Salesforce screens users enjoy and ones they work around. Our Salesforce custom development team builds LWC interfaces for portals, internal tools and complex data entry.
A sensible folder and naming convention
- Prefix components by feature, for example
orderSearch,orderResultsandorderDetail, so related pieces sit together. - Keep one Apex controller per feature with small, well-named methods rather than one giant utility class.
- Put shared utilities, such as date formatting or error handling, in a dedicated service component that others import.
- Use labels for user-facing text so translations and wording changes do not need code changes.
Handling errors gracefully
Users should never see raw stack traces. Wrap server calls, translate errors into plain messages with toast notifications or inline alerts, and log the technical details. A small shared function that extracts readable messages from the different error shapes Apex and Lightning Data Service return saves repetition across components.
Accessibility
- Prefer base components, which handle keyboard navigation and ARIA attributes.
- Give every input a visible label and every icon button an accessible name.
- Check color contrast and avoid conveying meaning with color alone.
- Test with the keyboard only: every action should be reachable without a mouse.
Common mistakes we fix
| Mistake | Better approach |
|---|---|
| Apex query for a single record the page already has | Use getRecord with the record ID |
| Huge components doing everything | Split into focused child components |
| Hard-coded record type or profile IDs | Query by developer name or use custom metadata |
| No loading or empty states | Show spinners and helpful empty messages |
| Server calls on every keystroke | Debounce input and search on the server |
Frequently asked questions
Should we still build Aura components?
For new work, Lightning Web Components are the recommended choice. Aura remains supported, and the two can work together during migration.
Can LWC be used outside Salesforce?
LWC is open source and can run outside the platform, but most business use is within Salesforce and Experience Cloud.
How do we test Lightning Web Components?
Use Jest for unit tests of component logic and rendering, and test end-to-end flows in a sandbox before release.



