Today I Learned
A collection of concise write-ups on small things I learn day to day across various languages and technologies.
Today I learned about using React.memo, useCallback, and useMemo to prevent unnecessary re-renders in React applications.
const MemoizedComponent = React.memo(function MyComponent(props) {
// Only re-renders if props change
});
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
const memoizedCallback = useCallback(() => doSomething(a, b), [a, b]);Container queries allow you to apply styles to an element based on the size of the element's container rather than the viewport size.
.container {
container-type: inline-size;
}
@container (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 2fr 1fr;
}
}Learned how to create GIN indexes on JSONB columns in PostgreSQL for faster querying of JSON data.
-- Create a GIN index on a JSONB column
CREATE INDEX idx_data ON table_name USING GIN (data_column);
-- Query using the index
SELECT * FROM table_name WHERE data_column @> '{"key": "value"}'::jsonb;Using multi-stage builds in Docker can significantly reduce the final image size by only including necessary artifacts from build stages.
# Build stage FROM node:16 AS build WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build # Production stage FROM nginx:alpine COPY --from=build /app/dist /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]
Practiced the HEAR technique (Halt, Engage, Anticipate, Replay) for better communication with team members during sprint planning.
Discovered that Ctrl+Shift+L selects all occurrences of the current selection, making bulk edits much faster.
// Some useful VS Code shortcuts: // Ctrl+Shift+L - Select all occurrences of current selection // Alt+Click - Insert cursor // Ctrl+D - Select next occurrence of current selection // Ctrl+/ - Toggle line comment
Learned how to configure S3 bucket policies to control access to objects while maintaining security best practices.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadForGetBucketObjects",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::example-bucket/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "203.0.113.0/24"
}
}
}
]
}Discovered best practices for managing Terraform state files in a team environment using remote backends.
# Configure the backend
terraform {
backend "s3" {
bucket = "terraform-state-prod"
key = "network/terraform.tfstate"
region = "us-west-2"
dynamodb_table = "terraform-locks"
encrypt = true
}
}Investigated and implemented strategies to minimize cold start latency in serverless applications using AWS Lambda.
// Optimize imports by moving them inside the handler when possible
exports.handler = async (event) => {
// Only load heavy dependencies when needed
const heavyDependency = event.needsHeavyProcessing
? require('heavy-library')
: null;
// Function logic here
return { statusCode: 200, body: 'Success' };
};Explored AWS Cloud Development Kit (CDK) for defining cloud infrastructure using familiar programming languages instead of YAML or JSON.
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';
export class MicroserviceStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Create VPC and Fargate Cluster
const vpc = new ec2.Vpc(this, 'ServiceVPC', { maxAzs: 2 });
const cluster = new ecs.Cluster(this, 'Cluster', { vpc });
// Define the Fargate Service
const taskDefinition = new ecs.FargateTaskDefinition(this, 'TaskDef');
taskDefinition.addContainer('AppContainer', {
image: ecs.ContainerImage.fromRegistry('my-app:latest'),
memoryLimitMiB: 512,
cpu: 256,
portMappings: [{ containerPort: 80 }]
});
// Create the service
const service = new ecs.FargateService(this, 'Service', {
cluster,
taskDefinition,
desiredCount: 2
});
// Set up load balancing
const lb = new elbv2.ApplicationLoadBalancer(this, 'LB', { vpc, internetFacing: true });
const listener = lb.addListener('Listener', { port: 80 });
listener.addTargets('Target', {
port: 80,
targets: [service]
});
// Output the load balancer URL
new cdk.CfnOutput(this, 'LoadBalancerDNS', { value: lb.loadBalancerDnsName });
}
}Learned how to properly configure CPU and memory limits for Kubernetes pods to optimize cluster resource utilization.
apiVersion: v1
kind: Pod
metadata:
name: frontend
spec:
containers:
- name: app
image: app:1.0.0
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
# Note: No CPU limit to avoid throttling
ports:
- containerPort: 80Learned how to use Docker Compose to define and run multi-container applications with a single configuration file.
version: '3.8'
services:
frontend:
build: ./frontend
ports:
- "3000:3000"
depends_on:
- backend
environment:
- API_URL=http://backend:8000
backend:
build: ./backend
ports:
- "8000:8000"
depends_on:
- database
environment:
- DB_HOST=database
- DB_USER=postgres
- DB_PASSWORD=example
- DB_NAME=myapp
database:
image: postgres:13
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=example
- POSTGRES_DB=myapp
volumes:
db-data:Những bài học thực tế khi phải bảo trì và nâng cấp hệ thống legacy code lớn trong môi trường doanh nghiệp.
// Ví dụ về Adapter Pattern để tách biệt code mới và cũ
// Interface mới
interface ModernPaymentProcessor {
processPayment(amount: number, currency: string): Promise<PaymentResult>;
}
// Adapter cho legacy code
class LegacyPaymentAdapter implements ModernPaymentProcessor {
private legacyProcessor = new LegacyPaymentSystem();
async processPayment(amount: number, currency: string): Promise<PaymentResult> {
// Chuyển đổi tham số cho hệ thống cũ
const legacyAmount = this.convertToLegacyFormat(amount, currency);
// Gọi hệ thống cũ
const result = this.legacyProcessor.makePayment(legacyAmount);
// Chuyển đổi kết quả sang định dạng mới
return this.convertToModernResult(result);
}
private convertToLegacyFormat(amount: number, currency: string): string {
// Logic chuyển đổi
return `${amount}|${currency}`;
}
private convertToModernResult(legacyResult: any): PaymentResult {
// Logic chuyển đổi kết quả
return {
success: legacyResult.status === "OK",
transactionId: legacyResult.id,
timestamp: new Date()
};
}
}