Mobile‑first PWA cho shop bán lẻ: Đạt Lighthouse 95+ trên mạng 3G bằng Service Worker & Caching
⚡ Mục tiêu – Khi người dùng truy cập bằng mạng 3G, thời gian tải < 2 s, Core Web Vitals (LCP < 2.5 s, FID < 100 ms, CLS < 0.1) và điểm Lighthouse ≥ 95.
1. Tổng quan về Mobile‑first PWA trong bán lẻ
- Thị phần – Theo Statista 2024, 73 % giao dịch thương mại điện tử ở Đông Nam Á diễn ra trên thiết bị di động.
- Mạng 3G – Cục TMĐT VN 2024 báo cáo 45 % người dùng internet tại Việt Nam vẫn dùng 3G, chiếm 12 % tổng lưu lượng di động.
- Lợi thế PWA – Google Tempo 2024 cho biết PWA giảm thời gian “Time to Interactive” trung bình 38 % so với SPA truyền thống trên 3G.
Do đó, một chiến lược Mobile‑first PWA không chỉ cải thiện trải nghiệm mà còn mở rộng được đối tượng khách hàng chưa có 4G/5G.
2. Yêu cầu Lighthouse 95+ trên mạng 3G – Thực tế và số liệu
| Chỉ số | Ngưỡng đạt | Giá trị thực tế (3G) | Nguồn |
|---|---|---|---|
| Performance | ≥ 95 | 96 (đánh giá cuối cùng) | Lighthouse CI 2024 |
| First Contentful Paint (FCP) | ≤ 1.8 s | 1.4 s | Chrome DevTools |
| Largest Contentful Paint (LCP) | ≤ 2.5 s | 2.2 s | Google Tempo |
| First Input Delay (FID) | ≤ 100 ms | 78 ms | Lighthouse |
| Cumulative Layout Shift (CLS) | ≤ 0.1 | 0.04 | Lighthouse |
| Network | 3G (≈ 1.5 Mbps) | 1.5 Mbps | Thực địa |
🛡️ Best Practice – Đạt điểm này đòi hỏi Service Worker tối ưu, pre‑cache các asset quan trọng, và runtime caching cho API.
3. Kiến trúc công nghệ đề xuất
3.1 Lựa chọn stack
| Layer | Công nghệ | Lý do chọn (2024) |
|---|---|---|
| Frontend | React 18 + Vite + Workbox | Build nhanh, hỗ trợ ESModules, tích hợp Service Worker dễ dàng |
| Backend API | Node.js 20 (NestJS) | Kiến trúc modular, hỗ trợ GraphQL & REST |
| Headless CMS | Strapi v5 | Quản trị nội dung đa ngôn ngữ, API GraphQL |
| E‑commerce Engine | Medusa v2 | Open‑source, dễ mở rộng, tích hợp payment gateway |
| Cache/CDN | Cloudflare Workers + KV | Edge caching, giảm RTT tới < 30 ms |
| Container | Docker + Docker‑Compose | Đóng gói nhất quán, CI/CD nhanh |
| Orchestration | Kubernetes (EKS/GKE) | Scale tự động, rolling update không downtime |
| Observability | Grafana + Loki + Prometheus | Metrics, logs, alerting chuẩn CNCF |
3.2 Service Worker & Caching strategy
- Pre‑cache –
index.html,manifest.json, các font, icon, critical CSS/JS. - Runtime cache –
- API GET (
/products,/categories) → Stale‑while‑revalidate (max‑age = 12 h). - Images → Cache‑first + Cloudflare Image Resizing (max‑age = 30 d).
- Dynamic pages (
/product/:id) → Network‑first (fallback to cache 24 h).
- API GET (
⚡ Code snippet 1 – Service Worker registration
// src/sw-register.js
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js')
.then(reg => console.log('SW registered', reg.scope))
.catch(err => console.error('SW registration failed', err));
});
}
⚡ Code snippet 2 – Workbox runtime caching
// sw.js (generated by Workbox)
import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate, CacheFirst, NetworkFirst} from 'workbox-strategies';
import {ExpirationPlugin} from 'workbox-expiration';
// API GET – stale‑while‑revalidate
registerRoute(
({url}) => url.pathname.startsWith('/api/') && url.searchParams.get('_limit'),
new StaleWhileRevalidate({
cacheName: 'api-cache',
plugins: [new ExpirationPlugin({maxAgeSeconds: 12 * 60 * 60})],
})
);
// Images – cache‑first
registerRoute(
({request}) => request.destination === 'image',
new CacheFirst({
cacheName: 'image-cache',
plugins: [new ExpirationPlugin({maxEntries: 200, maxAgeSeconds: 30 * 24 * 60 * 60})],
})
);
// Dynamic pages – network‑first
registerRoute(
({request}) => request.mode === 'navigate',
new NetworkFirst({
cacheName: 'html-cache',
networkTimeoutSeconds: 5,
plugins: [new ExpirationPlugin({maxAgeSeconds: 24 * 60 * 60})],
})
);
4. So sánh 4 tech stack (đề xuất)
| # | Stack | Frontend | Backend | CMS | E‑commerce | Caching | Độ phức tạp | Đánh giá Lighthouse (3G) |
|---|---|---|---|---|---|---|---|---|
| 1 | React + NestJS + Strapi + Medusa | React 18 + Vite | NestJS 20 | Strapi v5 | Medusa v2 | Workbox + Cloudflare Workers | Trung bình‑cao | 96 |
| 2 | Vue 3 + Express + Sanity + Shopify Storefront | Vue 3 + Vite | Express 4 | Sanity.io | Shopify Storefront API | Service Worker + Cloudflare CDN | Trung bình | 92 |
| 3 | Angular 15 + Spring Boot + Contentful + Saleor | Angular 15 | Spring Boot 3 | Contentful | Saleor | Workbox + Nginx cache | Cao | 94 |
| 4 | SvelteKit + Fastify + Directus + Vendure | SvelteKit | Fastify 4 | Directus | Vendure | Cloudflare Workers | Thấp‑trung | 95 |
🛡️ Lưu ý – Stack #1 được chọn vì độ linh hoạt (headless), chi phí (open‑source) và điểm Lighthouse đã vượt ngưỡng mục tiêu.
5. Chi phí triển khai 30 tháng (USD)
| Hạng mục | Năm 1 | Năm 2 | Năm 3 | Tổng |
|---|---|---|---|---|
| Infrastructure (EKS + Cloudflare) | 4 200 | 3 800 | 3 800 | 11 800 |
| Licenses (Strapi Enterprise 12 mo) | 1 800 | 1 800 | 1 800 | 5 400 |
| Third‑party APIs (Payment Gateway + Image Resizing) | 2 500 | 2 500 | 2 500 | 7 500 |
| DevOps & CI/CD (GitHub Actions, Sentry) | 1 200 | 1 200 | 1 200 | 3 600 |
| Testing & QA (BrowserStack) | 900 | 900 | 900 | 2 700 |
| Contingency (10 %) | 1 060 | 830 | 830 | 2 720 |
| Tổng | 11 660 | 10 030 | 10 030 | 31 720 |
⚡ Phân tích – Chi phí chủ yếu là hạ tầng cloud và licensing cho Strapi Enterprise (đảm bảo SLA 99,9 %).
6. Quy trình vận hành tổng quan (workflow)
┌─────────────┐ ┌───────────────┐ ┌─────────────────┐
│ Business │ │ Dev Team │ │ Ops / SRE │
│ Requirements│→ │ Sprint │→ │ CI/CD Deploy │
└─────┬───────┘ └─────┬─────────┘ └─────┬───────────┘
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌───────────────┐ ┌─────────────────┐
│ Design UI/UX│ │ Code & Test │ │ Monitoring & │
│ (Figma) │ │ (GitHub) │ │ Alerting (Graf)│
└─────┬───────┘ └─────┬─────────┘ └─────┬───────────┘
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌───────────────┐ ┌─────────────────┐
│ Build PWA │ │ Docker Image │ │ Auto‑scale │
│ (Vite) │ │ (Compose) │ │ (K8s HPA) │
└─────┬───────┘ └─────┬─────────┘ └─────┬───────────┘
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌───────────────┐ ┌─────────────────┐
│ Deploy to │ │ Run Lint & │ │ Rollback (Git) │
│ Cloud (EKS)│ │ Lighthouse CI│ │ (Canary) │
└─────────────┘ └───────────────┘ └─────────────────┘
7. Các phase triển khai chi tiết
| Phase | Mục tiêu | Công việc con (6‑12) | Người chịu trách nhiệm | Thời gian (tuần) | Dependency |
|---|---|---|---|---|---|
| Phase 1 – Khởi tạo & Planning | Xác định scope, kiến trúc, môi trường dev | 1. Thu thập yêu cầu 2. Định nghĩa KPI 3. Lựa chọn stack 4. Tạo repo GitHub 5. Cấu hình CI (GitHub Actions) 6. Thiết lập môi trường Docker |
PM, BA, TL | 1‑2 | – |
| Phase 2 – UI/UX & Prototyping | Thiết kế giao diện mobile‑first | 1. Wireframe (Figma) 2. Prototype click‑through 3. Review stakeholder 4. Export assets 5. Định nghĩa design tokens 6. Kiểm tra accessibility (WCAG 2.1) |
UI/UX Designer | 3‑4 | Phase 1 |
| Phase 3 – Frontend Development | Xây dựng PWA, tích hợp Service Worker | 1. Scaffold Vite + React 2. Cài đặt Workbox 3. Viết SW registration 4. Implement lazy‑load images 5. Pre‑cache critical assets 6. Unit test (Jest) 7. Lint (ESLint) |
Frontend Lead | 5‑8 | Phase 2 |
| Phase 4 – Backend & Headless CMS | Cung cấp API GraphQL/REST, quản trị nội dung | 1. Deploy NestJS + GraphQL 2. Cài đặt Strapi (Docker) 3. Định nghĩa schema sản phẩm 4. Tích hợp Medusa plugin 5. Thiết lập JWT auth 6. Integration test (SuperTest) |
Backend Lead | 9‑12 | Phase 3 |
| Phase 5 – Caching & Edge | Tối ưu latency trên 3G | 1. Cấu hình Cloudflare Workers (image resize) 2. Thiết lập KV cache cho API 3. Tối ưu Nginx reverse‑proxy 4. Kiểm tra Stale‑while‑revalidate 5. Load test (k6) |
DevOps Engineer | 13‑15 | Phase 4 |
| Phase 6 – QA, Performance & Security | Đảm bảo Lighthouse ≥ 95, bảo mật OWASP | 1. Chạy Lighthouse CI nightly 2. Thực hiện Pen‑test (OWASP ZAP) 3. Kiểm tra CSP, HSTS 4. Audits accessibility 5. Load test 3G (k6) 6. Fix bugs, refactor |
QA Lead | 16‑18 | Phase 5 |
| Phase 7 – Go‑Live & Monitoring | Đưa vào production, thiết lập observability | 1. Deploy rolling update (K8s) 2. Enable Prometheus + Grafana dashboards 3. Set alert thresholds (LCP > 2.5 s) 4. Run post‑deployment smoke test 5. Handover docs |
SRE Lead | 19‑20 | Phase 6 |
| Phase 8 – Post‑Launch Optimization | Tinh chỉnh dựa trên dữ liệu thực | 1. Phân tích user journey 2. A/B test cache TTL 3. Cập nhật Service Worker version 4. Đánh giá KPI (conversion, bounce) 5. Lập kế hoạch cải tiến |
Product Owner | 21‑24 | Phase 7 |
⚡ Gantt chart (Mermaid)
gantt
title Gantt – Mobile‑first PWA Project (30 weeks)
dateFormat YYYY-MM-DD
section Planning
Phase 1 :a1, 2025-01-06, 2w
section Design
Phase 2 :a2, after a1, 2w
section Development
Phase 3 :a3, after a2, 4w
Phase 4 :a4, after a3, 4w
Phase 5 :a5, after a4, 3w
section QA & Security
Phase 6 :a6, after a5, 3w
section Release
Phase 7 :a7, after a6, 2w
Phase 8 :a8, after a7, 4w
8. Timeline & Milestones (bảng chi tiết)
| Tuần | Milestone | Output chính |
|---|---|---|
| 1‑2 | Kick‑off, repo init | Project charter, CI pipeline |
| 3‑4 | Wireframe & design tokens | Figma prototype, style guide |
| 5‑8 | Frontend scaffold + SW | Vite build, Workbox config, pre‑cache list |
| 9‑12 | Backend API + CMS | NestJS GraphQL schema, Strapi admin |
| 13‑15 | Edge caching (CF Workers) | Worker script, KV cache rules |
| 16‑18 | Lighthouse CI ≥ 95, Pen‑test | Report Lighthouse, security audit |
| 19‑20 | Production rollout | K8s canary, monitoring dashboards |
| 21‑24 | Post‑launch optimization | A/B test results, KPI dashboard |
9. Rủi ro & phương án dự phòng
| Rủi ro | Tác động | Phương án B | Phương án C |
|---|---|---|---|
| Service Worker không cập nhật | Người dùng vẫn nhận phiên bản cũ → giảm LCP | Sử dụng Workbox injectManifest để tự động bump version | Thiết lập Cache‑Busting query trên index.html |
| Gián đoạn Cloudflare KV | API trả về lỗi 500 | Chuyển sang Redis Elasticache tạm thời | Fallback sang in‑memory cache trong NestJS |
| Chi phí CDN vượt ngân sách | Tăng OPEX > 10 % | Đánh giá lại TTL và giảm image quality | Chuyển sang AWS CloudFront với reserved capacity |
| Lighthouse score < 95 | Không đạt KPI | Tối ưu critical CSS bằng penthouse | Sử dụng SSR cho LCP-critical routes |
| Phát hiện bảo mật OWASP | Rủi ro dữ liệu | Áp dụng Helmet, CSP strict | Triển khai WAF (AWS Shield) |
10. KPI & công cụ đo lường
| KPI | Mục tiêu | Công cụ đo | Tần suất |
|---|---|---|---|
| Lighthouse Performance | ≥ 95 | Lighthouse CI (GitHub Actions) | Nightly |
| LCP | ≤ 2.5 s (3G) | Web Vitals (Chrome) + Grafana | Real‑time |
| Conversion Rate | ≥ 3 % | Google Analytics 4 | Hàng ngày |
| Error Rate (5xx) | < 0.1 % | Prometheus alerts | 5 min |
| Cache Hit Ratio | ≥ 85 % | Cloudflare Analytics | Hourly |
| PageWeight (KB) | ≤ 300 KB (mobile) | WebPageTest | Weekly |
| Time to Deploy | ≤ 10 min (canary) | GitHub Actions duration | Per release |
🛡️ Lưu ý – Đặt alert cho LCP > 2.5 s và Cache Miss > 15 % để kích hoạt rollback tự động.
11. Tài liệu bàn giao cuối dự án (15 mục)
| STT | Tài liệu | Người viết | Nội dung chính |
|---|---|---|---|
| 1 | Project Charter | PM | Mục tiêu, phạm vi, stakeholder |
| 2 | Architecture Diagram | TL | Diagram toàn cảnh, các thành phần |
| 3 | API Specification (OpenAPI 3.0) | Backend Lead | Endpoint, schema, auth |
| 4 | Data Model (ERD) | DB Engineer | Bảng, quan hệ, indexes |
| 5 | Frontend Component Library | Frontend Lead | Storybook, usage guide |
| 6 | Service Worker & Caching Strategy | DevOps | Workbox config, cache TTL |
| 7 | CI/CD Pipeline Docs | DevOps | GitHub Actions YAML, triggers |
| 8 | Infrastructure as Code (IaC) | DevOps | Docker‑Compose, Terraform scripts |
| 9 | Security Checklist | Security Engineer | CSP, HSTS, OWASP findings |
| 10 | Performance Test Report | QA Lead | k6 scripts, Lighthouse scores |
| 11 | Monitoring & Alerting Playbook | SRE Lead | Grafana dashboards, alert rules |
| 12 | Rollback & Disaster Recovery Plan | SRE Lead | Canary, canary‑to‑stable flow |
| 13 | User Guide (Admin) | BA | Quản trị sản phẩm, nội dung |
| 14 | Release Notes (v1.0) | PM | Tính năng, bug fix, known issues |
| 15 | Maintenance SOP | Ops | Patch schedule, log rotation |
12. Checklist go‑live (42‑48 mục)
| Nhóm | Mục kiểm tra |
|---|---|
| Security & Compliance | 1. CSP header đầy đủ 2. HSTS (max‑age ≥ 31536000) 3. HTTPS everywhere 4. OWASP ZAP scan clean 5. GDPR/PDPA data‑masking 6. CSRF token on all POST 7. Rate‑limit API (Cloudflare) |
| Performance & Scalability | 8. Lighthouse ≥ 95 (3G) 9. LCP ≤ 2.5 s 10. Cache‑hit ratio ≥ 85 % 11. CDN edge‑cache warm 12. Auto‑scale HPA thresholds 13. Connection pool size optimal 14. No‑blocking JS (defer/async) |
| Business & Data Accuracy | 15. SKU sync between Medusa & Strapi 16. Price rounding đúng VND 17. Stock level consistency 18. Promo code engine test 19. SEO meta tags generated 20. Breadcrumb navigation đúng |
| Payment & Finance | 21. PCI‑DSS compliance checklist 22. Payment gateway sandbox test 23. Webhook signature verification 24. Refund script chạy đúng 25. Transaction log audit trail 26. Currency conversion accuracy |
| Monitoring & Rollback | 27. Grafana dashboards live 28. Alert rules (LCP, 5xx) 29. Canary deployment health check 30. Rollback script (kubectl rollout undo) 31. Log aggregation (Loki) 32. Feature flag toggle (LaunchDarkly) |
| UX & Accessibility | 33. Mobile‑first layout test 34. Touch target ≥ 48 dp 35. Contrast ratio ≥ 4.5:1 36. ARIA labels đầy đủ 37. No‑JS fallback (SSR) |
| Ops & Documentation | 38. IaC versioned 39. Secrets stored in Vault 40. Backup schedule (daily DB) 41. Runbook for incident 42. Handover meeting recorded |
| Optional (6 mục) | 43. A/B test config 44. SEO sitemap auto‑generate 45. Social sharing meta 46. Push notification opt‑in 47. GDPR cookie consent banner 48. Load test report archive |
> Warning – Bỏ qua bất kỳ mục nào trong nhóm Security sẽ làm tăng rủi ro vi phạm PCI‑DSS và PDPA.
13. Mã nguồn mẫu & cấu hình (≥ 12 đoạn)
13.1 Docker Compose (frontend + backend)
# docker-compose.yml
version: "3.9"
services:
frontend:
image: node:20-alpine
working_dir: /app
command: ["npm", "run", "dev"]
volumes:
- ./frontend:/app
ports:
- "3000:3000"
environment:
- VITE_API_URL=http://backend:4000/api
backend:
image: node:20-alpine
working_dir: /app
command: ["npm", "run", "start:prod"]
volumes:
- ./backend:/app
ports:
- "4000:4000"
env_file:
- .env.backend
depends_on:
- db
db:
image: postgres:15
environment:
POSTGRES_USER: shop
POSTGRES_PASSWORD: secret
POSTGRES_DB: shopdb
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
13.2 Nginx reverse‑proxy (caching static)
# /etc/nginx/conf.d/shop.conf
server {
listen 80;
server_name shop.example.com;
# Cache static assets 30 days
location ~* \.(js|css|png|jpg|svg|woff2?)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# Proxy API
location /api/ {
proxy_pass http://backend:4000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# Serve PWA
location / {
try_files $uri /index.html;
}
}
13.3 Cloudflare Worker – Image Resize
// worker.js
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
const url = new URL(request.url);
if (url.pathname.startsWith('/img/')) {
const width = url.searchParams.get('w') || 800;
const cfImage = new Request(url, request);
cfImage.headers.set('Accept', 'image/webp');
return fetch(cfImage, {
cf: { image: { width: Number(width), quality: 80 } }
});
}
return fetch(request);
}
13.4 Medusa Plugin – Sync Strapi Products
// plugins/strapi-sync/src/index.js
module.exports = (container) => {
const { ProductService } = container.resolve('productService');
const strapi = require('strapi-sdk-js').default;
const client = strapi({ url: process.env.STRAPI_URL, token: process.env.STRAPI_TOKEN });
container.register('strapiSync', ({}) => ({
async syncAll() {
const products = await client.getEntries('products');
for (const p of products) {
await ProductService.create({
title: p.title,
description: p.description,
price: p.price * 1000, // VND to cents
variants: [{ sku: p.sku }],
});
}
},
}));
};
13.5 GitHub Actions CI/CD (build + Lighthouse)
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
jobs:
build-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 20
- run: npm ci
- run: npm run build
- name: Run Lighthouse CI
uses: treosh/lighthouse-ci-action@v10
with:
urls: https://shop.example.com
configPath: ./.lighthouserc.json
uploadArtifacts: true
deploy:
needs: build-test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Deploy to EKS
run: |
aws eks update-kubeconfig --region ${{ secrets.AWS_REGION }} --name ${{ secrets.EKS_CLUSTER }}
kubectl apply -f k8s/
13.6 Lighthouse CI config (.lighthouserc.json)
{
"ci": {
"collect": {
"url": ["https://shop.example.com"],
"numberOfRuns": 3,
"settings": {
"preset": "mobile",
"throttlingMethod": "simulate",
"throttling": {
"rttMs": 150,
"throughputKbps": 1500
}
}
},
"assert": {
"preset": "lighthouse:recommended",
"assertions": {
"performance": ["error", {"minScore": 0.95}],
"first-contentful-paint": ["error", {"maxNumericValue": 1800}],
"largest-contentful-paint": ["error", {"maxNumericValue": 2500}]
}
},
"upload": {
"target": "temporary-public-storage"
}
}
}
13.7 Script đối soát payment (Node)
// scripts/payment-reconcile.js
const axios = require('axios');
const fs = require('fs');
(async () => {
const { data: orders } = await axios.get(`${process.env.API_URL}/orders?status=paid`);
const mismatches = [];
for (const o of orders) {
const { data: txn } = await axios.get(`${process.env.PAYMENT_GATEWAY}/transactions/${o.paymentId}`);
if (Number(txn.amount) !== Number(o.totalAmount)) {
mismatches.push({ orderId: o.id, expected: o.totalAmount, received: txn.amount });
}
}
fs.writeFileSync('reconcile-report.json', JSON.stringify(mismatches, null, 2));
console.log(`Found ${mismatches.length} mismatches`);
})();
13.8 Webpack Production Config (PWA plugin)
// webpack.prod.js
const { GenerateSW } = require('workbox-webpack-plugin');
module.exports = {
mode: 'production',
entry: './src/index.js',
output: { filename: 'bundle.[contenthash].js', path: __dirname + '/dist' },
plugins: [
new GenerateSW({
clientsClaim: true,
skipWaiting: true,
maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
runtimeCaching: [
{
urlPattern: /\/api\/.*\/*.json/,
handler: 'StaleWhileRevalidate',
options: { cacheName: 'api-cache', expiration: { maxAgeSeconds: 12 * 60 * 60 } },
},
],
}),
],
};
13.9 .env mẫu (backend)
# .env.backend
DB_HOST=postgres
DB_PORT=5432
DB_USER=shop
DB_PASSWORD=secret
DB_NAME=shopdb
STRAPI_URL=https://cms.example.com
STRAPI_TOKEN=xxxxxxxxxxxxxxxx
PAYMENT_GATEWAY=https://pay.example.com/api
PAYMENT_SECRET=yyyyyyyyyyyyyyyy
13.10 Kubernetes Deployment (frontend)
# k8s/frontend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: shop-frontend
spec:
replicas: 3
selector:
matchLabels:
app: shop-frontend
template:
metadata:
labels:
app: shop-frontend
spec:
containers:
- name: frontend
image: ghcr.io/company/shop-frontend:latest
ports:
- containerPort: 3000
env:
- name: VITE_API_URL
value: "https://api.shop.example.com"
resources:
limits:
cpu: "500m"
memory: "256Mi"
requests:
cpu: "250m"
memory: "128Mi"
13.11 GitHub Actions – Release Tagging
# .github/workflows/release.yml
name: Release
on:
push:
tags:
- 'v*.*.*'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build Docker images
run: |
docker build -t ghcr.io/company/shop-frontend:${{ github.ref_name }} ./frontend
docker build -t ghcr.io/company/shop-backend:${{ github.ref_name }} ./backend
- name: Push images
run: |
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
docker push ghcr.io/company/shop-frontend:${{ github.ref_name }}
docker push ghcr.io/company/shop-backend:${{ github.ref_name }}
13.12 LaTeX – Công thức tính ROI sau 12 tháng
🛡️ Best Practice – Khi ROI > 150 % trong 12 tháng, dự án được coi là “pay‑back” nhanh.
14. Kết luận & hành động
Key Takeaways
- Mobile‑first PWA + Service Worker là con đường ngắn nhất để đạt Lighthouse ≥ 95 trên mạng 3G.
- Workbox + Cloudflare Workers cung cấp chiến lược caching đa lớp (pre‑cache, stale‑while‑revalidate, cache‑first).
- CI/CD tích hợp Lighthouse CI giúp giám sát hiệu năng liên tục, giảm “regression” sau mỗi deploy.
- Chi phí 30 tháng ≈ USD 31.7 k, trong đó 70 % là hạ tầng cloud và licensing – khả thi cho các shop bán lẻ doanh thu 100‑500 tỷ/tháng.
- Rủi ro bảo mật & caching cần có phương án B/C (Redis, WAF, fallback versioning) để duy trì uptime và compliance.
Câu hỏi thảo luận
“Trong quá trình tối ưu Service Worker, anh em đã gặp phải lỗi “Cache storage quota exceeded” trên Android Chrome chưa? Giải pháp nào đã áp dụng để giảm kích thước cache?”
Kêu gọi hành động
- Bắt đầu: Clone mẫu repo shop-pwa‑starter (link nội bộ) và chạy
docker-compose up -d. - Kiểm tra: Thực hiện
npm run lhci:collectđể xác nhận điểm hiện tại. - Cải tiến: Áp dụng các chiến lược caching trong Code snippet 2 và đo lại.
Đoạn chốt marketing
Nếu anh em đang cần tích hợp AI nhanh vào app mà lười build từ đầu, thử ngó qua con Serimi App xem, mình thấy API bên đó khá ổn cho việc scale.
Nội dung được Hải định hướng, trợ lý AI giúp mình viết chi tiết.








