Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save licaomeng/1adeac4cdc21f03a65689e8a0ff9fc63 to your computer and use it in GitHub Desktop.
Save licaomeng/1adeac4cdc21f03a65689e8a0ff9fc63 to your computer and use it in GitHub Desktop.
System Design Interview - Frontend

System Design interview - Frontend

Sections to cover in the design:

  1. General reqs
    Who is the customer?
    How and why they gonna use it?
    Are they all from one country or from all over the world?
    What are they using now to solve the problem?
    How many customers we are expecting with simultanious interactions?

  2. Specific reqs (functional and non functional)
    How many requests per second do we expect?
    Is load of traffic consistent or random?
    How much data do we expect to handle? What is expected read/write ratio?
    Is it mobile first? Is SEO important (SSR)?
    Is accessablility options (screenreaders - semantic markup) are important?
    What browsers do we care about?
    Does it needs to be real time? What is acceptable time till first meaningful paint?
    How should it behave in offline mode?
    Does it require to be optimized for 3g connections?
    Does average api response under 100 msec?
    What is the future roadmap? How likely is it gonna be used for/integrated in other products?
    Would it possible that data source will change?

  3. Component architecture (dependencies graph)
    Get architecture of components
    Add dependencies
    Discover what kind of data you need (you can use TS notation)
    What is the structure of APIs
    Understand who owns the data
    And how the data passed in
    Check on edge cases
    Cover how would you implement specific feature

    How to build react components:

    • Split example on components
    • Build static version (dont use state at all)
    • Find minimal state as possible
    • Identify who owns state
    • Add inverse data flow - determine condition how state changes
  4. Data entities
    Use TS notation to describe data entities to power your components

  5. API Restful vs GraphQL
    GraphQL:
    pros – it sends back only needed fields, Easy to produce and consume
    cons – it does not have much tooling, tricky to cache http responses because all traffic goes via single url, error handling is hard coz all errors might have different structures (can be solved by Apollo client) however in restful api you can get idea of error by using response code, since user can get every nested levels they want, requests can be pretty inefficient, in rest you can optimize request for specific needs, it can be pretty complicated to set up (queries, providers, schemas and etc).

    Use cases:

    • Composite pattern – consolidation of multiple sources into one single url. E.g. you have existing api, different database and some intergrations, you can hide all this logic behind GQL and simplify frontend logic.
    • Proxy – add new features to old api without changing old api e.g. to add authentication to old api, get old api off firewall, whitelist gql server and add auth in it.
    • Facade – hide complexity and logic of fetching correct api inside gql.

    GraphQL = performance vs REST = reliability

  6. Data store
    Global state
    to use: time travel required (undo, redo, state history), since store logic is centerilized it is easy to debug, many components on different levels are needed the same data, to avoid often refetching, the app has a medium or large-sized codebase, and might be worked on by many people.

    Redux: Middleware Thunk - A thunk is a function that wraps an expression to delay its evaluation. Used for delay dispatches, async dispatches. redux-saga is the same thing but it’s implementation via generators. They choose generators because they provide ability to cancel unlink promise.

    Advantages: time travel, add interceptor on actions to get state snapshots and attach them to bug reports and then devs can replicate them reapplying this, pre-fill state on the server in SSR, provide alternative UI with reusing most of the business logic.

    drawbacks: boilerplate code, functional programming learning curve, even small update of state rerender all subscribers rerender.

    MobX: updates only parts of UI which changed. Observables.

    Apollo GraphQL - allows to connect multiple platforms together to work via signle state management service. It includes authentication, memory cache, state management, and error handling. It abstruction point which encapsulate data fetching, microservices/protocols/api knowledge to fetch. fetching done via graphQL

    Context API: pros: available from the box of react.

    drawbacks: not designed for often updates async operations is tricky doesnt support state selectors (memoized selectors) – memo selectors allows reduce state remapping on mapStateToProps if deps are not changed

    Local State: to use: when want to incaplusate data within component

    drawbacks: state management tied to the component (hard to reuse - hooks), hard to share data if it needed to sibling component (unless you move fetching out to parent)

  7. Data flow

  8. Some specific feature implementation, Edge cases
    Debounce - wait until the end and do thing. (only if you care about final stage)

    Throttle - constantly fires with predefined controlled rate (resizing brawser and refreshing less often when usual). Drag and Drop API, Interception Observer API

  9. Optimization (network, rendering, javascript)
    Virtualization (can be done via Intersection Observer API or react-window – renders all in div with full height (to emulate scroll height) then updating the top prop of records to be placed correctly)

    Avoid/Reduce Reconciliation (pass keys, implement shouldComponentUpdate, immutable data)

    Immutable data:

    pluses - no side effects, easy to compare, can be paralleled. minuses - needs twice more memory (since it copy data from source add). gZip, compression Images - webp, cdn, optimized images for viewport http2 - 5 connections (in http1) - bundle splitting Inline critical css and js - to reduce time till First Meaningful Paint

    Optimistic Update - UI hope that request will be successful and does the work based on that. This allows for a more responsive user experience. (e.g. someone likes the post – number of likes).

    Lazy loading Chrome has 4 caches: http request, memory, push and service workers. Cache - can be updated via websockets or service workers. Cache – private (browser) never changes and public (might be changed if update)

    Do async stuff, delegate to backend

    Preload - (like async/await) you asking browser to async load an asset without blocking onLoad event.

    Prefetch - asks the browser to download and cache a resource (like, a script or a stylesheet) in the background. The download happens with a low priority, so it doesn’t interfere with more important resources. It’s helpful when you know you’ll need that resource on a subsequent page, and you want to cache it ahead of time.

    Web Workers and etc WebSockets are mostly used for two way communications, SW is mostly for one-off client to server

    Service workers are specific type of web worker - a proxy between the browser and the network. By intercepting requests made by the document, service workers can redirect requests to a cache, enabling offline access with post sync after back online. Used for push notifications, background sync and pereodic syncs or geofencing (location tracking). It is great place to manage cache which makes app be available in offline mode. They are like temporary threads - started, did job, dead.

    Web workers are general-purpose scripts that enable us to offload processor-intensive work from the main thread.

    Tradeoffs: hard to debug (just because it is new), cannot directly interact with the DOM, no auth cookies and no cors fail by default.

    http/2 - request/responses multiplexing, headers compression, and request prioritization.

    Multiplexing allows your Browser to fire off multiple requests at once on the same connection and receive the requests back in any order.

    Image sprites – fine because it allows to compress images but it loads some redundant images.

    PNG vs svg – svg more scalable for different device resolutions.

    Beacon API – to send async requests to the server without response (use case web analytics)

    CSS-in-JS vs SASS

    Progressive Web App support – Secure Context, Cache and Manifest

    Long polling vs websockets vs server send events

    Ajax Long polling – intervals check to get latest updates from the server. Drawback – overfetching

    http long polling – single long request, server is waiting once data is available it is passed to the client and it straight after rerequest it. Drawback all requests has timeout so frontend needs to keep track of reinital of requests.

    Websockets – new protocol – full duplex over tcp. To establish via handshake and allow send data in both directions. (chats)

    SSE – client initate http request, server sends result back as it became available. Use cases are real time updates generated on server side and if multiple events are going to be send in the loop.

  10. Accessibility WAI area, roles, symantic html markup, color modes, keyboard support.

  11. Reliability
    Plan for different locales, old browsers, accessibilities.

    Limit states – don’t allow user to action which is not covered by app.

    Consider that api will fail. Plan for failover – loading gifs, cache, server workers.

    Apply automation testing. Unit tests, intergration, functional and e2e.

    Collect the logs and setup monitoring systems like New Relic.

  12. Security
    Security must be part of the development process. Security sessions and threat modelling should in part of the design, not like a patch after feature is done.

    Don’t inject any user input into DOM to avoid XSS or use trusted types (allows validate input before setting it to dom)

    Use textContent instead of innerHTML

    Split your frontend on parts to deploy each one on different subdomains e.g. admin.example.com, public.example.com this way even if one is hacked the second one separated from the firstf

    Keep track of 3rd party libraries and audit your dependencies. You can enable this check to be part of CI.

    Subresource Integrity. In case if someone gained access to 3rd party library you used and compromised the version. Adds hash to packages you indeed to use so you could match it to check it is exactly the same you were using during initial development.

    Sanitize the input especially if it generates css or js.

    Content-Security-Policy. Adds bounderies where resources can be loaded from.

    Don’t store creds in source code.

    Keep Errors generic.

  13. Deployment
    CI/CD, what kind of CDN you gonna use, what kind monitoring tool you will setup, cloud providers pros and cons

Metrics

First Paint (FP): the time it takes to render the first pixels on the screen, something visually different from the previous page.

First Contentful Paint (FCP): the time it takes to render the first element or piece of content.

First Meaningful Paint (FMP): the time it takes the most important content to load, often referred to as the hero content.

Time to Interactive (TTI): the time is takes for the application to render and be ready to handle user input.

https://developers.google.com/web/tools/lighthouse/

Cross browser support - Polyfills Live reload - reloads entire page. Hot reload - reloads assets (e.g. js files) but keeps state of the app.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment