การจัดการ Repo มีผลต่อประสิทธิภาพของทีม (ภาค Monorepo)
Tech giant เจ้าใหญ่ๆ อย่าง Google, Facebook, Twitter รวม project ต่างๆ ให้อยู่ใน repo เดียวกัน หรือเรียกว่า Monorepo (1, 2, 3) แถม branch ยังมีแค่ branch เดียวอีกด้วย เรียกว่า Trunk based development
Concept Monorepo นี้ขัดกับพวก Front-end development มาก เพราะ project ของ NPM มักจะสนับสนุน 1 repo ต่อ 1 package ไม่พอ Trunk based development ก็ขัดกับ concept ของ git ที่สนับสนุน distributed workflow มี feature branch มี local repo มี fork มี pull request ซึ่งแทบจะอยู่ขั้วตรงข้ามกัน
ถึงตอนนี้ขอแยกเป็น 2 ประเด็น ระหว่าง Monorepo กับ Trunk based development
เริ่มที่ Monorepo เราจะไป Monorepo บ้างดีไหม? ลองย้อนไปดูจุดประสงค์ว่าทำไมเจ้าใหญ่ๆ ถึงทำอย่างนี้ จาก presentation ของ Google ในงาน @ scale บอกเหตุผลที่ใช้ Monorepo ดังนี้
- ประโยชน์ในการจัดการ package
- มีแค่ Version เดียว เป็น Single source of truth
- จัดการกับ dependency ง่าย
- ทำให้เห็นภาพรวมว่ามี package อะไรบ้าง - ประโยชน์ในการทำ cross package change
- การแก้ไขต่างๆ อยู่ใน commit เดียวกัน
- ช่วยเรื่อง refactoring, technology modernization - ประโยชน์ในการช่วยกันทำงาน
- ช่วยในการแชร์ code และ reuse
- เป็นการทำงานร่วมมือกันข้ามทีม
- ทำให้ไม่มีเส้นแบ่งระหว่างทีม และเส้นแบ่งระหว่าง code ว่าอันไหนของใคร
คราวนี้ดูข้อเสียบ้าง
- อาจจะต้องมี tool ช่วย (มีคนรวม tool ไว้ ที่นี่)
- จำนวน code เยอะเกินไป อาจมีผลต่อ productivity
- ต้องทำให้ code health ดีตลอดเวลา (เช่น ถ้ามีคนทะลึ่งทำ build พัง จะมีผลกระทบต่อทุกคน)
ถ้า Dev ของคุณต้องแก้ project นึง แล้ว deploy แล้วต้องมาแก้อีก project นึง แล้วดึง dependency มาใหม่ สลับไปสลับมา ผมว่า เราอาจจะเริ่มดู Monorepo เป็นแนวทางแล้วก็ได้นะครับ
Monorepo สำหรับ Front-end development
สำหรับ Front-end dev เราจะสามารถทำ Monorepo ได้อย่างไร? ในเมื่อ NPM ไม่ได้มี concept Module เหมือน Maven เรามาดูกันว่าจะมี tool อะไรช่วยเราได้บ้าง
- Lerna เป็น tool สำหรับ bootstrap และ publish package NPM หลายๆ ตัวพร้อมกัน
- Yarn Workspaces เป็น feature ของ Yarn ในการจัดการหลายๆ package ใน project เดียวกัน
- Bit อันนี้ค่อนข้างฉีกแนว ประมาณว่าคุณไม่ต้องไป Monorepo ก็ได้ แต่ถ้าอยากแก้ไข component ใน package อื่น เรามี command ให้คุณสามารถแก้ไขได้เลย โดยที่ไม่ต้องออกจาก project
- Meta อันนี้ก็ฉีกแนว ประมาณว่าแต่ละ package ก็อยู่แยก repo ไปเลย แล้วใช้ command ในการสั่งงานพร้อมๆ กันหลาย repo
- Alle อันนี้ไม่ใช่ tool แต่เป็น technique ประมาณว่าก็เอา project ต่างๆ ไปไว้ใน folder ชื่อ node_modules ซึ่ง node มันจะไป lookup folder ต่างๆ ใน node_modules ให้อัตโนมัติอยู่แล้ว
ส่วนตัวผม ผมชอบ Yarn Workspaces กับ Alle เพราะว่าไม่ต้องลง tool เพิ่ม และไม่มี package ซ้ำจากการ install package.json ใน folder ต่างๆ
Shared repo
อีก topic นึงคือ ถ้าเรามี Package ที่เป็น library กลาง แต่เรามี 2 project ขึ้นไปที่อยากใช้ library นี้ ทีนี้เราก็อยากให้ project ต่างๆ สามารถ contribute กลับเข้าไป project กลางได้ด้วย ตาม concept ของ Monorepo มี tool อะไรบ้างที่ช่วยเราทำเรื่องนี้ มาดูกัน
- Nested git repo ก็คือมี git repo อยู่ใน folder ของ git อีกตัว วิธีนี้มีข้อเสียคือ tool บางตัวไม่รองรับ และคนที่ clone ไป ไม่ได้ข้อมูลของ git อีกตัวที่อยู่ข้างใน
- Git submodule วิธีนี้คือการ link repo แล้วชี้ไปที่ commit ของอีก repo นึง ข้อเสียคือ change จะไม่อยู่ใน commit เดียวกัน และเราต้อง commit งานใน repo ย่อยก่อนเสมอ
- Git subtree ถ้าคุณใช้ SourceTree ก็จะมีคำสั่ง subtree ให้ใช้เลย git subtree นี้มีข้อเสียนิดหน่อยคือเวลา clone จะไม่มีข้อมูล subtree ไปด้วย และถ้า repo มีขนาดใหญ่ เวลาแยก commit ไป subtree จะค่อนข้างช้า
- Git subrepo แนะนำให้ใช้ release 0.4.0 (ซึ่งปัจจุบัน master ยังเป็น 0.3.1) คุณสมบัติเหมือน subtree แต่เวลา clone จะมีข้อมูล subrepo ติดไปด้วย และ commit ไป subrepo จะเร็วกว่า subtree
จบแล้วครับสำหรับ Monorepo คราวหน้ามาคุยกันต่อเรื่อง Trunk based development