ไม่มีชื่อบทความ
Best Practice CI ใน Monorepo
TL;DR
- ใช้ TurboRepo ร่วมกับ
pnpm filterเพื่อรันงาน CI แยกส่วน ลด build time - ตั้ง GitHub Actions ให้ใช้ matrix สร้างงานแยกตามแอป/แพ็กเกจ พร้อม cache
pnpm-store& Turbo cache - เพิ่ม status badge ใน README แสดงผลลัพธ์ CI เร็วขึ้นชัดเจน (เช่น จาก 15 → 4 นาที)
1. ปัญหาปัจจุบัน
- Monorepo ใหญ่ มีหลายแอป/แพ็กเกจ ทำ CI ทีเดียว build ทั้งหมด → ใช้เวลานาน
- ไม่มีการแยกงานตาม scope → รัน
pnpm install+turbo run buildซ้ำหลายครั้ง - Cache ไม่ครบถ้วน → ติดตั้ง dependency ใหม่ทุกครั้ง
2. แนวทางปรับปรุงหลัก
Matrix Build: แยก CI job ตาม
apps/*และpackages/*pnpm filter: ให้แต่ละ job รันเฉพาะ scope ที่ต้องการ
Cache:
actions/cacheสำหรับ~/.pnpm-store- Turbo remote cache หรือ local cache ระหว่าง job
Parallelism: รันหลาย job พร้อมกันได้บน GitHub Actions
Status Badge: แสดงผลลัพธ์ที่ README เพื่อกระตุ้นทีมเห็นความเร็ว
3. โครงสร้าง Workflow (YAML)
name: CI Monorepo
on:
push:
branches: [main, dev]
pull_request:
branches: [main, dev]
jobs:
setup:
runs-on: ubuntu-latest
outputs:
pnpm-cache-key: ${{ steps.cache-pnpm.outputs.cache-hit }}
steps:
- uses: actions/checkout@v3
# Cache pnpm store
- name: Cache pnpm store
id: cache-pnpm
uses: actions/cache@v3
with:
path: ~/.pnpm-store
key: pnpm-store-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
restore-keys: pnpm-store-${{ runner.os }}-
# Setup Node.js + pnpm
- name: Setup Node.js & pnpm
uses: pnpm/action-setup@v2
with:
version: 18
run_install: false
- name: Install dependencies
run: |
$ pnpm install --frozen-lockfile --store-dir ~/.pnpm-store
build:
needs: setup
runs-on: ubuntu-latest
strategy:
matrix:
scope: [apps/web, apps/admin-dashboard, packages/ui-kit]
steps:
- uses: actions/checkout@v3
# Restore pnpm store cache
- name: Restore pnpm store
uses: actions/cache@v3
with:
path: ~/.pnpm-store
key: pnpm-store-${{ runner.os }}-${{ needs.setup.outputs.pnpm-cache-key }}
- name: Setup Node.js & pnpm
uses: pnpm/action-setup@v2
with:
version: 18
run_install: false
- name: Install dependencies
run: |
$ pnpm install --frozen-lockfile --store-dir ~/.pnpm-store
- name: Run build for ${{ matrix.scope }}
run: |
$ pnpm --filter ${{ matrix.scope }} build
4. ตัวอย่าง Matrix
| scope | คำสั่งรัน |
|---|---|
apps/web |
$ pnpm --filter apps/web build |
apps/admin-dashboard |
$ pnpm --filter apps/admin-dashboard build |
packages/ui-kit |
$ pnpm --filter packages/ui-kit build |
ประโยชน์:
- Build เฉพาะส่วนที่เปลี่ยนหรือสำคัญ
- Parallel run → ใช้เวลารวมสั้นลง
- ง่ายต่อการ debug job ที่ล้ม
5. Cache pnpm Store & Turbo
5.1 pnpm store
- เก็บใน
~/.pnpm-store - Cache ด้วย
actions/cacheตามpnpm-lock.yaml
5.2 TurboCache
เปิด Remote Cache (เช่นบน S3) หรือใช้ Local Disk
ใน
turbo.jsonตั้งค่า:{ "pipeline": { "build": { "dependsOn": ["^build"], "outputs": [".next/**", "dist/**"] } }, "remoteCache": { "enabled": true, "url": "https://<turbo-cache-endpoint>" } }เพิ่ม step ใน CI:
- name: Restore Turbo Cache uses: turborepo/action@v1 with: command: remote-restore - name: Save Turbo Cache uses: turborepo/action@v1 with: command: remote-store
6. Status Badge
เพิ่มใน README.md:

- แสดงผลแบบ real-time
- กระตุ้นทีมเห็นการปรับปรุง build time
7. ตารางเปรียบเทียบ Build Time (Speed-up)
| Scenario | Before (monolithic) | After (matrix + cache) | Speed-up |
|---|---|---|---|
| ติดตั้ง dependency + build | 15 min | 4 min | 3.75× |
Build apps/web |
– | 1.5 min | – |
Build apps/admin-dashboard |
– | 1.2 min | – |
Build packages/ui-kit |
– | 0.8 min | – |
| Full CI total (parallel jobs) | 15 min | 2 min | 7.5× |
หมายเหตุ: เวลาในตารางเป็นตัวอย่าง เบื้องต้นทดสอบบน GitHub-hosted runners
8. Tips & Best Practices
✅ ใช้
--frozen-lockfileป้องกันเปลี่ยน lockfile โดยไม่ตั้งใจ✅ รัน lint และ test แยกตาม scope ได้เช่นกัน:
- name: Run lint run: pnpm --filter ${{ matrix.scope }} lint - name: Run tests run: pnpm --filter ${{ matrix.scope }} test✅ กำหนด timeout ให้แต่ละ job ไม่เกิน 10 นาที
✅ ใช้ artifact เก็บผลลัพธ์หากต้อง debug
9. สรุป
- แยก CI job ตาม scope → ลดงาน build ที่ไม่จำเป็น
- Cache pnpm store + Turbo → ลดเวลาติดตั้งและ build ซ้ำ
- Matrix build → parallelism ชัดเจน
- Status badge + ตาราง speed-up → แสดงผลลัพธ์ทีมมองเห็นได้ง่าย
หลังปรับแล้ว Dev สามารถ merge PR ได้เร็วขึ้น ลด waiting time ของทีม Nokfa เหลือไม่กี่นาที!