parent
dbf2353a41
commit
d87ea1c972
29 changed files with 373 additions and 19 deletions
@ -0,0 +1,13 @@ |
||||
1. **In-Memory Cache**: Use tools like Redis or Memcached for quick access to frequently used data. Common use case is caching results of expensive database queries. |
||||
|
||||
2. **HTTP Caching**: Leverage `Cache-Control` headers for client-side and proxy caching. |
||||
|
||||
3. **Application-Level Caching**: Store calculated values or frequently used objects in memory using libraries like `express-cache` or decorators. |
||||
|
||||
4. **Distributed Caching**: In distributed systems, use a shared cache (e.g., Redis) to ensure consistency across instances. |
||||
|
||||
5. **Cache Invalidation**: Use strategies like time-to-live (TTL) or event-driven invalidation to keep the cache up-to-date. |
||||
|
||||
6. **Testing**: Monitor cache hit rates and ensure no stale data is served. |
||||
|
||||
**Browser Caching**: While not strictly server-side, take advantage of browser caching to store static resources client-side, reducing backend requests. |
@ -0,0 +1,7 @@ |
||||
Build tools bundle, optimize, and prepare your code for deployment. |
||||
|
||||
**Key Functions**: |
||||
* Bundle JavaScript, CSS, and other assets. |
||||
* Minify and optimize files for faster loading. |
||||
* Enable features like hot module replacement (during development). |
||||
* Handle modern JavaScript (transpile ES6+ to older versions). |
@ -0,0 +1,20 @@ |
||||
**CI/CD Pipelines** automate the build, test, and deployment of any project. These pipelines are a critical part of any successful development process. |
||||
|
||||
##### Continuous Integration (CI): |
||||
In this step you automatically build and test the code whenever changes are pushed to a repository. The usual tools for the job are Jenkins, GitHub Actions, CircleCI and other similar alternatives. |
||||
|
||||
##### Continuous Delivery (CD): |
||||
During this phase, the actual deployment of the product is automated, so that once the code is verified in the CI stage, it can automatically be promoted into the right environment. |
||||
|
||||
##### Steps in a Pipeline: |
||||
The steps involved in the full process are: |
||||
|
||||
Pull code → Build app → Run tests → Deploy artifact → Notify team |
||||
|
||||
And all of them are done automatically one after the other, breaking the chain if there is a failure in one of them. |
||||
|
||||
##### Most common tools used: |
||||
1. **Jenkins**: Highly customizable for complex workflows. |
||||
2. **GitHub Actions**: Easy integration with GitHub repositories. |
||||
3. **Docker**: For containerized builds. |
||||
4. **ArgoCD** or **Spinnaker**: For Kubernetes deployments. |
@ -0,0 +1,8 @@ |
||||
A full-stack application includes one or more web pages, a backend (which usually involve microservices) and some sort of storage engine (i.e a database). |
||||
To deploy all of that together, you have to: |
||||
|
||||
1. **Prepare the Application**: Build the frontend (e.g., using `npm run build`). Ensure the back-end is production-ready (e.g., environment variables, database setup). |
||||
2. **Deploy Frontend**: Push the code into the servers, usually something like AWS S3, GCP Cloud Storage, or Firebase Hosting to host static files. Configure a CDN (e.g., CloudFront) if needed for static content. |
||||
3. **Deploy Back-End**: Use cloud services like AWS EC2, GCP Compute Engine, or a managed platform like AWS Elastic Beanstalk. Set up environment variables and connect to the database (e.g., RDS, Cloud SQL). |
||||
4. **Database**: Use a managed database service (e.g., RDS, Firestore) for scalability, or deploy an on-prem database on your server. |
||||
5. **DNS and SSL**: Configure a custom domain and HTTPS using AWS Route 53, GCP Domains, or another provider. |
@ -0,0 +1,17 @@ |
||||
**Code splitting** breaks a large application into smaller bundles that are loaded only when needed. |
||||
|
||||
**Benefits**: |
||||
* Reduces initial load time by loading only essential code and downloading the rest when needed. |
||||
* Improves performance for slower networks by allowing webapp use much sooner. |
||||
|
||||
**Example using React's `lazy` and `Suspense`**: |
||||
```javascript |
||||
const LazyComponent = React.lazy(() => import('./Component')); |
||||
|
||||
function App() { |
||||
return ( |
||||
<Suspense fallback={<div>Loading...</div>}> |
||||
<LazyComponent /> |
||||
</Suspense> |
||||
); |
||||
} |
@ -0,0 +1,17 @@ |
||||
1. **Challenge**: Managing State Across Frontend and Backend. |
||||
* **Solution**: Use global state management tools (e.g., Redux, Zustand) and APIs with clear data contracts. |
||||
|
||||
2. **Challenge**: Scalability Issues. |
||||
* **Solution**: Optimize database queries, implement caching, and use scalable cloud infrastructure. |
||||
|
||||
3. **Challenge**: Security Concerns. |
||||
* **Solution**: Implement secure authentication (e.g., OAuth2), sanitize inputs, and follow OWASP guidelines. |
||||
|
||||
4. **Challenge**: Maintain a consistent quality level across the entire codebase (both frontend and backend code). |
||||
* **Solution**: Implement a robust testing strategy that includes: unit testing, integration testing, end-to-end testing, and regular code reviews. |
||||
|
||||
5. **Challenge**: Keeping Up with Technology Updates. |
||||
* **Solution**: Adopt modular architecture to replace outdated tech incrementally. |
||||
|
||||
6. **Challenge**: Debugging Complex Interactions Between Frontend and Backend. |
||||
* **Solution**: Use end-to-end testing frameworks (e.g., Cypress) and logging tools for tracing issues. |
@ -0,0 +1,12 @@ |
||||
**CORS** (Cross-Origin Resource Sharing) controls access to resources from a different origin (domain, protocol, or port). |
||||
|
||||
**Handling CORS**: |
||||
|
||||
**Backend**: Set headers to allow specific origins. |
||||
Example in Express: |
||||
```javascript |
||||
const cors = require('cors'); |
||||
app.use(cors({ origin: 'https://example.com' })); |
||||
``` |
||||
|
||||
**Frontend**: Proxy API requests to avoid CORS issues during development. |
@ -0,0 +1,17 @@ |
||||
1. **Version Control**: Track migrations using tools like Flyway, Liquibase, or Sequelize. |
||||
|
||||
2. **Create Safe Migration Scripts**: |
||||
* Avoid destructive changes like dropping columns immediately |
||||
* Break migrations into additive steps: |
||||
- Add new columns |
||||
- Backfill data |
||||
- Remove old columns later |
||||
|
||||
3. **Testing**: |
||||
* Test migrations in a staging environment with a copy of production data |
||||
|
||||
4. **Rollback Plans**: |
||||
* Write scripts to revert migrations in case of failure |
||||
|
||||
5. **Zero-Downtime Deployment**: |
||||
* Use techniques like dual writes and feature flags to ensure smooth transitions |
@ -0,0 +1,18 @@ |
||||
Docker containerizes applications and their dependencies, ensuring they run consistently across environments. |
||||
|
||||
**In Development**: |
||||
* Provides isolated environments (e.g., for different projects). |
||||
* Simplifies onboarding (e.g., no need to manually install dependencies). |
||||
|
||||
**In Deployment**: |
||||
* Ensures consistent environments between dev and production. |
||||
* Integrates with orchestration tools (e.g., Kubernetes) for scalability. |
||||
|
||||
Example Dockerfile: |
||||
```dockerfile |
||||
FROM node:14 |
||||
WORKDIR /app |
||||
COPY . . |
||||
RUN npm install |
||||
CMD ["npm", "start"] |
||||
``` |
@ -0,0 +1,11 @@ |
||||
**Event-Driven Architecture**: A design pattern where services communicate by emitting and responding to events asynchronously. |
||||
|
||||
**Key Components**: |
||||
* **Event Producer**: Generates events (e.g., a user uploads a file). |
||||
* **Event Consumer**: Listens and reacts to events (e.g., a service processes the uploaded file). |
||||
* **Message Broker**: Facilitates event delivery (e.g., Kafka, RabbitMQ). |
||||
|
||||
**When to Use**: |
||||
* Applications needing real-time updates (e.g., chat apps, stock trading platforms). |
||||
* Decoupled microservices to enhance scalability and maintainability. |
||||
* Workflows with asynchronous tasks (e.g., order processing). |
@ -0,0 +1,9 @@ |
||||
1. **Reproduce the Issue**: Identify when and where it happens. |
||||
2. **Frontend Debugging**: |
||||
* Use browser DevTools to inspect network requests (e.g., check HTTP status codes, payloads). |
||||
* Check console errors for clues. |
||||
3. **Back-End Debugging**: |
||||
* Check server logs for errors or trace logs for the request. |
||||
* Add breakpoints or use a debugger (e.g., Node.js Inspector). |
||||
4. **Communication Point**: Verify API endpoints, payload structure, and data format. |
||||
5. **End-to-End Testing**: Test the workflow with tools like Postman to isolate the layer causing issues. |
@ -0,0 +1,27 @@ |
||||
GraphQL is a query language for APIs that allows clients to request exactly the data they need, reducing over-fetching or under-fetching. |
||||
|
||||
##### Main differences with REST: |
||||
|
||||
**Data Fetching**: |
||||
* REST: Fixed endpoints return predefined data |
||||
* GraphQL: Single endpoint with flexible queries |
||||
|
||||
**Batching**: |
||||
* GraphQL can fetch related data in one request (nested queries) |
||||
* REST often requires multiple endpoints for related data |
||||
|
||||
**Versioning**: |
||||
* REST may need new versions for API changes |
||||
* GraphQL avoids versioning by evolving schemas |
||||
|
||||
**Example GraphQL Query**: |
||||
```graphql |
||||
query { |
||||
user(id: 1) { |
||||
name |
||||
posts { |
||||
title |
||||
} |
||||
} |
||||
} |
||||
``` |
@ -0,0 +1,13 @@ |
||||
**High Availability**: |
||||
* Use load balancers to distribute traffic across multiple servers |
||||
* Set up redundancy with failover systems and multiple availability zones |
||||
* Use managed databases with replicas for disaster recovery |
||||
|
||||
**Scalability**: |
||||
* Implement horizontal scaling by adding more instances |
||||
* Use auto-scaling services like AWS Auto Scaling or Kubernetes |
||||
* Cache frequently accessed data (e.g., using Redis or Memcached) |
||||
|
||||
**Other Best Practices**: |
||||
* Optimize database queries and use indexing |
||||
* Implement rate limiting and throttling to handle surges |
@ -0,0 +1,18 @@ |
||||
**Frontend**: Use libraries like `react-intl` or `i18next` to manage translations. |
||||
|
||||
Example: |
||||
```javascript |
||||
import { useTranslation } from 'react-i18next'; |
||||
const { t } = useTranslation(); |
||||
<h1>{t('welcome_message')}</h1>; |
||||
``` |
||||
|
||||
**Backend**: |
||||
1. Store translations in a database or JSON files. |
||||
2. Serve the correct language file based on user preferences or `Accept-Language` headers. |
||||
|
||||
**Additional Considerations**: |
||||
* Support language-specific routes (e.g., `/en/home`, `/fr/home`) |
||||
* Translate content dynamically from the database or CMS |
||||
* Provide fallback languages if a translation is unavailable |
||||
* Test language switches and correct text alignment for RTL languages like Arabic |
@ -0,0 +1,22 @@ |
||||
Memory leaks usually happen when unused resources (e.g., DOM elements, event listeners, or data structures) are not properly released, causing unnecessary memory consumption. |
||||
|
||||
**Common Solutions**: |
||||
|
||||
1. **Clean up event listeners**: Remove listeners when components unmount: |
||||
```javascript |
||||
useEffect(() => { |
||||
window.addEventListener('resize', handler); |
||||
return () => window.removeEventListener('resize', handler); |
||||
}, []); |
||||
``` |
||||
|
||||
2. **Abort fetch requests**: Use `AbortController` to cancel pending API calls: |
||||
```javascript |
||||
const controller = new AbortController(); |
||||
fetch(url, { signal: controller.signal }); |
||||
return () => controller.abort(); |
||||
``` |
||||
|
||||
3. **Avoid stale references**: Ensure state updates do not persist after unmounting by checking component state. |
||||
|
||||
4. **Use profiling tools**: Monitor and analyze memory usage using browser DevTools to detect leaks. |
@ -0,0 +1,15 @@ |
||||
1. **Decompose the Application**: Identify distinct business domains and split functionality into small, loosely coupled services. |
||||
|
||||
2. **Service Communication**: |
||||
* Use APIs (REST or GraphQL) for synchronous communication |
||||
* Use messaging systems (e.g., RabbitMQ, Kafka) for asynchronous communication |
||||
|
||||
3. **Independent Data Stores**: Each service manages its own database to ensure independence. |
||||
|
||||
4. **Service Discovery**: Use a registry like Consul or Eureka to manage service locations dynamically. |
||||
|
||||
5. **Deployment**: |
||||
* Containerize services with Docker |
||||
* Orchestrate using Kubernetes |
||||
|
||||
6. **Monitoring**: Use tools like Prometheus, Grafana, or ELK Stack for observability and debugging. |
@ -0,0 +1,8 @@ |
||||
**MVC** is a design pattern for organizing code in three layers: |
||||
|
||||
1. **Model**: Handles data and business logic (e.g., database interactions). |
||||
2. **View**: Displays data to users (e.g., HTML, templates). |
||||
3. **Controller**: Manages user input and communicates between Model and View. |
||||
|
||||
**Flow**: |
||||
* User interacts with the **View** → **Controller** processes input → Updates the **Model** → Changes are reflected in the **View**. |
@ -0,0 +1,18 @@ |
||||
As a full-stack developer, the monitoring of your application involves the full 360 view of the app, from the frontend into the backend, including the database, and other involved systems. |
||||
|
||||
##### Frontend Monitoring: |
||||
* Use tools like Google Lighthouse or Web Vitals to track load times, interactivity, and rendering. |
||||
* Monitor user behavior with tools like New Relic Browser or LogRocket. |
||||
|
||||
##### Backend Monitoring: |
||||
* Use APM tools (e.g., Datadog, Dynatrace) to monitor server response times, database query performance, and API latency. |
||||
|
||||
##### Logging: |
||||
* Centralize logs with tools like ELK Stack or CloudWatch Logs for analyzing bottlenecks. |
||||
* Critical for systems with many individual microservices and different clients working together. |
||||
|
||||
##### Database Monitoring: |
||||
* Use query profilers (e.g., MySQL EXPLAIN) and monitor database health with tools like Percona Monitoring. |
||||
|
||||
##### Alerting: |
||||
* Set up alerts for anomalies or thresholds using tools like Prometheus and Grafana. |
@ -0,0 +1,14 @@ |
||||
1. **Create a Request**: Enter the API endpoint, method (GET, POST, etc.), and headers. |
||||
2. **Send Data**: |
||||
* Add query params, body (JSON, form data), or headers. |
||||
3. **Send Request**: Click "Send" to view the response. |
||||
|
||||
**Assertions**: Use the **Tests** tab to write scripts (JavaScript) for automated validation of responses. |
||||
Example: |
||||
```javascript |
||||
pm.test("Status is 200", () => { |
||||
pm.response.to.have.status(200); |
||||
}); |
||||
``` |
||||
|
||||
4. **Collections**: Group requests for testing workflows or environments. |
@ -0,0 +1,6 @@ |
||||
1. **Server-Side Rendering (SSR)**: Use frameworks like Next.js to render pages on the server for better crawlability. |
||||
2. **Meta Tags**: Dynamically set titles, descriptions, and keywords using libraries like `react-helmet`. |
||||
3. **Sitemap and Robots.txt**: Generate a sitemap.xml and configure robots.txt for search engines. |
||||
4. **Lazy Loading**: Ensure above-the-fold content loads quickly. |
||||
5. **Structured Data**: Add JSON-LD for rich search results. |
||||
6. **Canonical URLs**: Avoid duplicate content issues with proper canonical tags. |
@ -0,0 +1,14 @@ |
||||
The easiest way is to use a framework like **Next.js** for built-in SSR support. |
||||
|
||||
**Steps involved**: |
||||
|
||||
1. Set up pages with `getServerSideProps` to fetch data at request time: |
||||
```javascript |
||||
export async function getServerSideProps() { |
||||
const data = await fetch('https://api.example.com'); |
||||
return { props: { data } }; |
||||
} |
||||
``` |
||||
|
||||
2. Render the page server-side and send it as HTML to the client. |
||||
3. Hydrate the page on the client to make it interactive. |
@ -0,0 +1,21 @@ |
||||
1. **Use WebSockets**: Establish a persistent connection for real-time communication. |
||||
|
||||
Example Client: |
||||
```javascript |
||||
const socket = new WebSocket('ws://server.com'); |
||||
socket.onmessage = (message) => console.log(message.data); |
||||
``` |
||||
|
||||
2. **Server Setup**: Use libraries like `socket.io` for WebSocket management. |
||||
|
||||
Example Server: |
||||
```javascript |
||||
const io = require('socket.io')(server); |
||||
io.on('connection', (socket) => { |
||||
socket.on('chat message', (msg) => io.emit('chat message', msg)); |
||||
}); |
||||
``` |
||||
|
||||
3. **Fallback for Compatibility**: Implement long polling or server-sent events (SSE) if WebSockets aren't feasible. |
||||
4. **Database Integration**: Use event-driven solutions like Redis pub/sub for scalability in multi-server setups. |
||||
5. **Security**: Ensure secure WebSocket connections (wss://) and authenticate users. |
@ -0,0 +1,21 @@ |
||||
##### SQL Injection: |
||||
|
||||
To avoid SQL injection attacks, use parameterized queries or prepared statements to prevent malicious SQL code from being executed: |
||||
```javascript |
||||
db.query('SELECT * FROM users WHERE id = ?', [userId]); |
||||
``` |
||||
|
||||
Also validate and sanitize user inputs to ensure it doesn't contain characters that might interfere with SQL statements. |
||||
|
||||
##### Cross-Site Scripting (XSS): |
||||
|
||||
To avoid allowing scripts or dynamic content to affect your page: |
||||
|
||||
1. Escape content before rendering in the browser: |
||||
```javascript |
||||
<div>{sanitize(userInput)}</div> |
||||
``` |
||||
|
||||
2. Use libraries like DOMPurify to sanitize HTML. |
||||
|
||||
3. Set `Content-Security-Policy` headers to restrict allowed sources for scripts to trusted sources. |
Loading…
Reference in new issue