Frontend
-
Use the right (semantic) HTML element for the job eg. headings, lists, etc.
Validate HTML markup with https://validator.w3.org/nu/.header-footer-main-nav-asidecan be used for layout.detail-summarycan be used to mimic an accordion.progress-metercan be used to show a progress bar.em-strong-markcan be used to indicate importance of text.- MathML for mathematical equations.
-
Descriptions on elements, eg.
altattribute on images,titleattribute on link tags, and<label>tag to form elements.loadingattribute to defer assets & embeds like images, and iframe.<img src="image.jpg" loading="lazy" alt="Description" /> <iframe src="video.html" loading="lazy"></iframe> -
Using native keyboard accessibility eg. providing
role, ortabIndexattribute. https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/ -
Web is global, so ideally anything on web should easily be adapted for different regions, or languages.
<!DOCTYPE html> <!-- Webpage Localization using `lang` attribute. --> <html lang="en"></html> <!-- Alternate Localized webpages with hreflang attribute --> <link hreflang="en" href="https://example.com" rel="alternate" /> <!-- hreflang should include the link to current language as well! --> -
Consider UI design fundamentals:
- Contrast:
Contrast ratio of 4.5:1 for normal text (less than 18 point or 14 point bold.)
Contrast ratio of 3:1 for large text (at least 18 point or 14 point bold.) - Visual Hierarchy:
Headings must not break hierarchical structure.
- Contrast:
How Browsers Work
- DNS Lookup → TCP Connection → HTTP Request
- HTML Parsing → DOM Construction
- CSS Parsing → CSSOM Construction
- Render Tree → Layout → Paint → Composite
flowchart LR
HTML --> DOM[DOM Tree]
CSS --> CSSOM
DOM --> RT[Render Tree]
CSSOM --> RT
RT --> Layout
Layout --> Paint
Paint --> Composite
Minimize critical path length by optimizing the order in which critical resources are loaded.
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="dns-prefetch" href="https://api.example.com" />
<link rel="preload" href="critical.css" as="style" />
<link rel="prefetch" href="next-page.html" />
WAI-ARIA
"Web Accessibility Initiative - Accessible Rich Internet Applications" allows a set of additional HTML attributes to provide semantics and accessibility, wherever it is lacking. These are broadly categorized into:
- Roles define what an element is or does eg. navigation (
<nav>), complementary (<aside>), banner, search, tablist, tabpanel, button, etc. - Properties give extra meaning or semantics to elements eg. aria-required, aria-label, aria-labelledby, etc.
- States define the current conditions of elements eg aria-disabled, etc.`
<!-- Semantic HTML first -->
<button aria-label="Close dialog" aria-expanded="false">
<span aria-hidden="true">×</span>
</button>
<!-- Live regions -->
<div aria-live="polite" id="status"></div>
<div aria-live="assertive" id="errors"></div>
<!-- Landmarks -->
<nav aria-label="Main navigation">
<main aria-labelledby="main-heading">
<aside aria-label="Related links"></aside>
</main>
</nav>
Web Security
-
Click-Jacking: Set the
SameSitecookie attribute for session cookies to 'Lax' or 'Strict'.- Use
sandboxattribute gives embedded content only the permissions needed. Never add bothallow-scriptsandallow-same-originto sandbox attribute. - Send
X-Frame-Optionsheader to prevent other websites from embedding your content.
Read More: https://blog.mozilla.org/security/2013/12/12/on-the-x-frame-options-security-header/
- Use
-
Session hijacking: Use
HTTPSto reduce chances of content tampering during transit, and to prevent embedded content from accessing parent document, and vice versa. -
Cross-site scripting (XSS): Always Sanitize user input.
Content Security Policy (CSP) provides a set of HTTP Headers that allows website administrators to control resources the user agent is allowed to load for a given page.<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline'" /> -
Cross-site request forgery (CSRF / XSRF): Include CSRF token in requests.
// Include CSRF token in requests fetch("/api/data", { method: "POST", headers: { "X-CSRF-Token": document.querySelector('[name="csrf-token"]').content, }, body: JSON.stringify(data), });
CORS
A bane of all web-devs, a boon to all web-surfers. Read more: https://jakearchibald.com/2021/cors/
Web Data Sharing
- Cookies: Cookies is data saved by server on browser to support stateful behaviour.
- SessionStorage: SessionStorage is saved as keys and values, partitioned by both origin and browser tabs.
- LocalStorage: LocalStorage data is saved as keys and the values in the UTF-16 string format, and has no expiration time.
LocalStorage data is specific to the protocol of the document, and is available across browser instances or tabs. - IndexedDB: A NoSQL storage system
- Memory:
Browsers can store up to 5 MiB of local storage, and 5 MiB of session storage per origin.
Web Vitals
Popular metrics measuring many of the various aspects of performance relevant to users:
- First Contentful Paint (FCP): measures the time from when the page starts loading to when any part of the page's content is rendered on the screen. (lab, field)
- Largest Contentful Paint (LCP): measures the time from when the page starts loading to when the largest text block or image element is rendered on the screen. (lab, field)
- First Input Delay (FID): measures the time from when a user first interacts with your site (when they click a link, tap a button, or use a custom, JavaScript-powered control) to the time when the browser is actually able to respond to that interaction. (field)
- Interaction to Next Paint (INP): measures the latency of every tap, click, or keyboard interaction made with the page, and—based on the number of interactions—selects the worst interaction latency of the page (or close to the highest) as a single, representative value to describe a page's overall responsiveness. (lab, field)
- Time to Interactive (TTI): measures the time from when the page starts loading to when it's visually rendered, its initial scripts (if any) have loaded, and it's capable of reliably responding to user input quickly. (lab)
- Total Blocking Time (TBT): measures the total amount of time between FCP and TTI where the main thread was blocked for long enough to prevent input responsiveness. (lab)
- Cumulative Layout Shift (CLS): measures the cumulative score of all unexpected layout shifts that occur between when the page starts loading and when its lifecycle state changes to hidden. (lab, field)
- Time to First Byte (TTFB): measures the time it takes for the network to respond to a user request with the first byte of a resource. (lab, field)
Each Core Web Vitals metric has associated thresholds, which categorize performance as either "good", "needs improvement", or "poor":
| Good | Poor | Percentile | |
|---|---|---|---|
| Largest Contentful Paint | <2500ms | >4000ms | 75 |
| Interaction to Next Paint | <200ms | >500ms | 75 |
| Cumulative Layout Shift | <0.1 | >0.25 | 75 |
UI Loading Patterns
How and when content is loaded is important. The approaches can broadly classified under
- Static Import: Everything is bundled & served together.
- Dynamic Import: Bundles are segmented and served only when needed. They are preceeded by placeholders which hydrate later.
- Import on visibility: Bundles are served when they in/near the viewport.
- Import on interaction: Bundle are served on user action, eg. button click to expand a section.
- Data Loading:
- XMLHttpRequest: XHR objects are used retrieve data without having to do a full page refresh.
- Fetch: Fetch is promise-based modern replacement for XMLHttpRequest.
A few advanced paradigms could be adopted to provided further breakdown on resource timeline.
- PRPL
- Pushing critical resources efficiently to minimize roundtrips to the server.
- Rendering the initial route soon as possible.
- Pre-caching assets in the background.
- Lazily loading routes or assets that aren’t requested as frequently.
- Islands Architecture: The static regions of the page are pure non-interactive HTML and do not need hydration. The dynamic regions are a combination of HTML and scripts capable of rehydrating themselves after rendering.
- Unlike Progressive Hydration where the hydration architecture of the page is top-down, each component has its hydration script in the Islands architecture that executes asynchronously, independent of any other script on the page.
UI Architecture Patterns
-
MVC (Model-View-Controller)
flowchart LR U[User Input] --> C[Controller] C --> M[Model] M --> V[View] V --> U- Model: Data and business logic
- View: UI representation
- Controller: Handles user input
-
MVP (Model-View-Presenter)
flowchart LR U[User Input] --> V[View] V <--> P[Presenter] P <--> M[Model]- View is passive, Presenter handles all logic
- Better testability than MVC
-
MVVM (Model-View-ViewModel)
flowchart LR U[User Input] --> V[View] V <--> VM[ViewModel] VM <--> M[Model]- Data binding between View and ViewModel
- Popular in WPF, Angular, Vue.js
-
MVI (Model-View-Intent)
flowchart LR I[Intent] --> M[Model] M --> V[View] V --> I- Unidirectional data flow
- Reactive programming approach
-
VIPER (iOS Architecture):
Read more: https://medium.com/@pinarkocak/understanding-viper-pattern-619fa9a0b1f1- View: UI components
- Interactor: Business logic
- Presenter: View logic
- Entity: Data models
- Router: Navigation logic
Browser DevTools Tips
- Performance Profiling
- Lighthouse: Audit performance, accessibility, SEO
- Performance Tab: Analyze runtime performance
- Network Tab: Optimize resource loading
- Memory Tab: Debug memory leaks
- Debugging Techniques: Instead of sprinkling
consolestatements around, addition ofdebugger;statement adds a programmatic breakpoint. - Custom Metrics: The Web Performance Working Group has also standardized lower-level APIs that can be useful for implementing your own custom metrics:
- Performance Observer API
- User Timing API
- Long Tasks API
- Element Timing API
- Event Timing API
- Resource Timing API
- Navigation Timing API
- Server Timing API
Must know libraries
- Styling
- Stylesheet Generators
- bootstrap (Sass / Scss)
- tailwind
- vanilla-extract
- Styled Components
- css-modules
- Stylesheet Generators
- Iconography
- Sprites
- SVG
- State Management Libraries
- Redux
- Zustand
- Apollo
- Routing Libraries
- React-Router
- Component Libraries
- React-Bootstrap
- Ant Design
- MUI
- Mantine
- RadixUI
- Functionality Libraries
- Formik
- Zod
- Framer Motion
- RxJS