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: 80
Learned 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() }; } }