DEV Community

Woraphol Wananiyakul
Woraphol Wananiyakul

Posted on

แชร์ประสบการณ์ลอง migrate จาก pnpm ไป yarn berry กัน

เนื่องจากได้เห็นโพสต์ที่เกี่ยวกับ yarn berry แล้วเลยอยากลองที่จะ migrate จากตัวที่ใช้ pnpm ไป berry ก็เลยเกิดเป็นโพสต์นี้ครับ

ก่อนเริ่ม

จริงๆแล้วผมเคยได้ยินyarn (berry) มานานมาแล้วแต่ไม่เคยลองเพราะว่าช่วงนั้นผมเคยเห็น issue ที่ใช้แล้ว project ไม่สามารถรันได้เลยก็เลยคิดว่ารอสักพักค่อยมาลองสุดท้ายก็ลืม -.-

Timeline

ตั้งแต่เข้าสู่วงการ dev ผมก็เริ่มที่ npm -> yarn(classic) -> pnpm(ปัจจุบัน)

ขอย้อนไปตอนที่ใช้ yarn classic (หลังจากนี้จะขอย่อว่า classic) ผมใช้ feature นึงคือตัว worksapcesใช้มาประมาณ 3 ปีได้แล้วถ้านับไม่ผิด และก็เมื่อไม่นานมานี้ผมได้เห็นตัว pnpm เป็นที่พูดถึงกันก็เลยลองไปดูว่ามันเป็นยังไงมี feature ไหนบ้าง

หลังจากที่ไปดูว่าโดยรวมถือว่าโอเคเลยมีทุก feature ที่ผมใช้หลังจากนั้นโปรเจคช่วงๆหลังผมจะเป็น pnpm ทั้งหมด

ปัจจุบัน

ก่อนที่จะเข้าหัวข้อหลักคือ yarn berry มาดูตัวอย่าง structure ที่ผมใช้ pnpm แบบอย่างง่ายตาม example เลยก็ว่าได้แล้วจะแปลงเป็นในรูปแบบของ yarn berry

├── packages 
│   └── moduleA
│         └── package.json ──
│   └── moduleB              │ 
│         └── package.json   │  moduleC เรียกใช้ moduleA
│   └── moduleC              │ 
│         └── package.json __│ 
├── package.json 
├── pnpm-workspace.yaml // <- pnpm เอาไว้ใช้ประกาศ workspace
Enter fullscreen mode Exit fullscreen mode
  • packages รวม modules ต่างๆไว้ในนี้, submodule จะเป็น typescript project ทั้งหมด

ตัวอย่างโค้ดของแบบ pnpm อยู่ repo นี้ -> example pnpm code

required nodejs >= 14.7

อธิบายเพิ่มเติมจาก code

  • module{A,B,C} จะเป็น typescript ทั้งหมดโดยจะให้มัน compile ออกมาเป็น esm format รวมถึง *.d.ts เผื่อให้แต่ละ module มี type ของตัวมันเอง
  • moduleC จะเรียกใช้ moduleA สังเกตได้จากตัว package.json และจะเรียกใช้ใน index.ts

ทั้งหมดนี้เมื่อ compile และ run จะทำงานได้ถูกต้อง

getTheBestSong จาก moduleA จะเกิด Bug ไม่ว่าเราจะใส่ parameter ให้หรือไม่ใส่มันก็จะออกแต่ strawberry moon ❤️

Yarn (Berry)

หลังจากที่ไม่ได้พูดถึงเลยก็จะขอกลับมาพูดแบบย่อสักนิด

ข้อดีคร่าวๆของตัว berry

  • เปลี่ยนการ resolve dependency ใหม่
  • เพิ่ม ecosystem ของตัวเอง (plugin) e.g. plugin-typescript
  • constraints e.g. ในแต่ละ workspaces ต้องมี dependencies, library, devDependencies ที่เวอร์ชั่นเท่ากัน
  • offline Cache

และแน่นอน workspaces

ข้อเสีย

  • ส่วนตัวว่า doc ยังทำความเข้าใจได้อยากอยู่และตัวอย่างน้อย

อ่านเพิ่มเติมได้ที่ doc

ปรับ pnpm ให้อยู่ในรูปแบบ berry

tools

  • set yarn version berry ด้วย command yarn set version berry
  • ลง vscode extension
  • run command yarn dlx @yarnpkg/sdks vscode (เพื่อให้ vscode รู้การ resolve ที่ไม่ใช่จากตัว node_module)

จากโค้ด pnpm ข้างบน

  • ลบ folder node_modules/ (แน่นอนจะไม่มี node_module แล้ว)
  • ลบ pnpm-workspace.yaml, pnpm-lock.yaml
  • เพิ่ม workspaces ใน package.json ใน root project
  • ใน moduleC เรียกใช้ workspace moduleA ใน package.json

หลังจากทำตามข้างบนเรียบร้อยแล้วไปที่ root directory run command yarn เพื่อ install dependency

หลังจากที่ install แล้วจะเห็นว่ามันจะไม่มี node_module อีกต่อไปแล้วแต่จะมาในรูปแบบของ javascript file แทน ในที่นี้คือ .pnp.cjs เปรียบเสมือน node_module นั่นเองแล้วที่นี้มันจะไปดู dependencies ที่ไหนละคำตอบก็คือในโฟลเดอร์ .yarn/cache สังเกตว่า berry จะโหลด deps มาในรูปแบบ zip

เรียบแล้วแล้วตอนนี้ project ของเราก็จะอยู่ในรูปแบบของ workspace(berry)
ทีนี้ก็ลอง build ทั้งโปรเจคโดย run command yarn workspaces foreach run build

มันจะแจ้งเตือนให้ลง plugin เพิ่ม (ecosystem อันใหม่) run command yarn plugin import workspace-tools

เมื่อลงเสร็จลอง build ใหม่ตาม command ข้างบนทีนี้ก็เป็นการเสร็จสิ้น

แต่เดี๋ยวก่อนนน...

ถ้าเกิดลองไปดูที่ moduleC จะเห็นว่ามันจะแจ้งเตือนหา moduleA ไม่เจอ ซึ่งผมก็ติดอยู่ตรงนี้แหละไม่ได้ไปต่อ ซึ่งลองไปดู issue ก็จะมีคนติดปัญหาที่คล้ายๆแบบนี้ก็เลยไม่ได้ไปลอง feature อื่นๆต่อ

แต่ถ้า project เป็น javascript ไม่ใช่ typescript สามารถทำงานได้ปกติ

โค้ดของ berry -> example berry code

สรุป

ปัญหาข้างบนเป็นในกรณีที่เราใช้ตัว workspaces แต่ถ้าไม่ได้ใช้ workspaces ตัว berry ทำงานได้ปกติ (resolve ได้ปกติ)

ทั้งหมดนี้ก็เป็นประสบการณ์ที่ผมได้เจอในการลองที่จะย้ายค่ายกลับมาใช้ yarn, ปัญหาที่เกิดขึ้นอาจจะเกิดที่ผมเซ็ตไม่ถูกต้องก็ได้ครับและถ้ามีโอกาสได้กลับมาแก้หรือมันแก้ไข้อะไรยังไงเรียบร้อยแล้วจะมาแชร์อีกทีครับ

ทั้งหมดนี้ถ้าผมสื่อสารผิดพลาดหรือทำให้งงยังไงก็ขอโทษด้วยนะครับจะพยายามปรับปรุงเรื่อยๆครับ ขอบคุณครับ 🙏

Refs

Discussion (0)