Prisma 7 รื้อ Prisma Client ใหม่ ทิ้ง Rust engine ที่เคยพกไปด้วย · Prisma เคลม bundle เล็กลง ~90% แต่ย้ายจาก v6 ยังมีของต้องแก้
Prisma 7 รื้อ Prisma Client ขึ้นใหม่ ทิ้ง Rust query engine ที่ทำให้ bundle ใหญ่และ deploy ยากบน serverless แต่ v7 เป็น breaking upgrade ต้องเพิ่ม driver adapter และย้ายโค้ดที่ generate มาไว้ในโปรเจกต์เอง นี่คือสิ่งที่ควรรู้ก่อนย้ายจาก v6

Prisma คือเครื่องมือที่นักพัฒนาสาย Node และ TypeScript ใช้เขียนโค้ดจัดการฐานข้อมูล ตอนนี้ขยับขึ้นเวอร์ชัน 7 แล้ว รอบนี้ไม่ใช่การอัปเดตเล็ก ๆ เพราะทีมงานรื้อ Prisma Client ซึ่งเป็นหัวใจของเครื่องมือขึ้นมาใหม่แทบทั้งตัว สิ่งแรกที่เอาออกคือ query engine ที่เป็นไบนารีภาษา Rust หรือโปรแกรมแยกอีกก้อนที่ Prisma Client รุ่นก่อนต้องพกไปด้วยทุกครั้งที่ deploy
พอไม่ต้องแบกไบนารี Rust ไปด้วย Prisma Client รุ่นใหม่จึงเป็น ESM หรือโมดูล JavaScript แบบมาตรฐานล้วน ๆ Prisma เคลมว่า bundle หรือขนาดของโค้ดที่ต้องแพ็กไปด้วยเล็กลงราว 90 เปอร์เซ็นต์ และ query เร็วขึ้นสูงสุด 3 เท่า
อีกจุดที่เห็นได้ชัดคือเรื่องที่อยู่ของโค้ด เดิมทีโค้ด client ที่คำสั่ง prisma generate สร้างให้จะไปซ่อนอยู่ใน node_modules ซึ่งเป็นโฟลเดอร์ที่เราแทบไม่เคยเปิดดู แต่ v7 ย้ายโค้ดนี้ออกมาไว้ในโปรเจกต์ของเราตรง ๆ ทั้งหมดนี้ฟังดูดี แต่ก็มีสิ่งที่ต้องแลก เพราะ v7 เป็น breaking upgrade ที่มีของต้องแก้อยู่หลายอย่างก่อนจะย้ายจาก v6 ได้
ของหนักที่ Prisma Client เคยแบกไว้
ก่อนจะเห็นว่า v7 ดีขึ้นตรงไหน ต้องเข้าใจของเดิมก่อน Prisma Client รุ่นก่อนหน้านี้ไม่ได้เป็นแค่โค้ด JavaScript ธรรมดา แต่มี query engine ที่เป็นไบนารี Rust อีกก้อนหนึ่งคอยทำงานด้วย ไบนารีตัวนี้รับคำสั่งจากโค้ดของเรา แล้วแปลงเป็นคำสั่ง SQL ที่ฐานข้อมูลเข้าใจ มันทำงานได้ดี แต่ข้อแลกเปลี่ยนคือขนาดที่ใหญ่ขึ้น เพราะทุกครั้งที่ deploy เราต้องพาไบนารีก้อนนี้ไปด้วยเสมอ
ปัญหานี้เจ็บที่สุดตอน deploy ขึ้น serverless หรือ edge อย่าง Vercel, Cloudflare Workers หรือ AWS Lambda เพราะทุกเมกะไบต์มีผลต่อเวลา cold start และบางแพลตฟอร์มก็จำกัดขนาด bundle เอาไว้ตายตัว พอเป็นแบบนี้ การต้องแบกไบนารี Rust ไปด้วยจึงกลายเป็นงานที่ต้องคอยจัดการ
ยังมีอีกจุดที่กวนใจ คือโค้ด client ที่ prisma generate สร้างขึ้นมาจะไปอยู่ใน node_modules ซึ่งเป็นโฟลเดอร์ที่เราไม่ได้เปิดแก้เอง เวลาอยากรู้ว่า client ทำงานยังไง หรือเจอบั๊กแล้วอยากไล่โค้ดดู ก็ทำได้ยาก เพราะโค้ดไปซ่อนอยู่ในที่ที่เรามองแทบไม่เห็น
v7 ทิ้ง engine เก่า แล้วสร้าง client ขึ้นใหม่

หัวใจของ v7 คือ generator ตัวใหม่ชื่อ prisma-client ซึ่งเป็น client แบบ ESM ที่ไม่ต้องพึ่ง Rust query engine อีกต่อไป จริง ๆ แล้วตัวนี้มีมาตั้งแต่เวอร์ชัน 6.16 ในฐานะตัวเลือกที่ต้องเปิดใช้เอง แต่พอมาถึง v7 ก็กลายเป็นค่าเริ่มต้นของทุกโปรเจกต์ที่สร้างใหม่
ถ้าจะเปลี่ยนมาใช้ ให้แก้บรรทัดเดียวในไฟล์ schema.prisma คือเปลี่ยนค่า provider จาก prisma-client-js เป็น prisma-client
generator client {
- provider = "prisma-client-js"
+ provider = "prisma-client"
}ตัวเลขที่ว่า bundle เล็กลงราว 90 เปอร์เซ็นต์ query เร็วขึ้นสูงสุด 3 เท่า และ deploy ง่ายขึ้นนั้น Prisma ระบุไว้เองใน release notes ของเวอร์ชัน 7.0.0 ตรงนี้ต้องย้ำว่าเป็นตัวเลขที่ Prisma เคลมเอง ยังไม่มีการวัดจากภายนอกมายืนยัน จึงควรอ่านเป็นทิศทาง ไม่ใช่ตัวเลขที่พิสูจน์แล้ว
คำว่า Rust-free ก็ต้องเข้าใจให้ตรง หมายถึงการเอา query engine ที่เป็นไบนารี Rust แยกก้อนออกไป หรือก็คือตัวที่เคยทำให้ bundle บวม ไม่ได้แปลว่าทั้งระบบของ Prisma จะไม่มี native code เหลืออยู่เลย เพราะส่วนอื่นอย่าง driver adapter หรือบริการฝั่งเซิร์ฟเวอร์ยังมีชิ้นส่วนของตัวเองได้
โค้ดที่เคยซ่อน ย้ายมาอยู่ตรงหน้า
จุดที่เห็นภาพชัดที่สุดของ v7 คือเรื่องที่อยู่ของโค้ด เวอร์ชันนี้บังคับให้เราตั้งค่า output ในไฟล์ schema.prisma ว่าจะให้ prisma generate เขียนโค้ด client ออกมาไว้ที่ไหน และ Prisma แนะนำให้วางไว้ในโฟลเดอร์ src ของโปรเจกต์ไปเลย
generator client {
provider = "prisma-client"
output = "../src/generated/prisma"
}พอตั้งค่าแบบนี้ เวลาสั่ง prisma generate โค้ด client จะไปโผล่ในโฟลเดอร์ที่เรากำหนดไว้ แล้วเราก็ import เข้ามาใช้จากตรงนั้นได้เลย
import { PrismaClient } from './generated/prisma/client';
สิ่งที่ต่างออกไปคือ โค้ดที่เคยซ่อนอยู่ใน node_modules กลายเป็นไฟล์ที่อยู่ในโปรเจกต์ของเราเหมือนไฟล์อื่น ๆ เปิดดูได้ ไล่โค้ดตอน debug ได้ และเห็นชัดว่า client ตรงกับ schema ล่าสุดหรือยัง ของที่เคยเป็นเหมือนกล่องดำ กลายเป็นของที่เราจับต้องและควบคุมได้
ของที่ต้องแก้ก่อนย้ายจาก v6

ถึงตรงนี้ต้องพูดกันตรง ๆ ว่า v7 ไม่ใช่การอัปเกรดที่กดปุ่มแล้วจบ แต่เป็น breaking upgrade ที่มีของต้องแก้ สามเรื่องหลักที่จะเจอทันทีมีดังนี้
เรื่องแรก ทุกครั้งที่สร้าง client ด้วย new PrismaClient() ตอนนี้ต้องส่ง driver adapter เข้าไปด้วยเสมอ การเรียก new PrismaClient() เปล่า ๆ หรือส่งค่า datasources และ datasourceUrl แบบเดิมใช้ไม่ได้แล้ว ส่วน adapter ที่ต้องใช้ก็ขึ้นอยู่กับฐานข้อมูลของคุณ
- Postgres ใช้ @prisma/adapter-pg
- SQLite ใช้ @prisma/adapter-better-sqlite3
- MySQL หรือ MariaDB ใช้ @prisma/adapter-mariadb
หน้าตาโค้ดที่ต่อกับ Postgres จะประมาณนี้
import { PrismaClient } from './generated/prisma/client';
import { PrismaPg } from '@prisma/adapter-pg';
const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL });
const prisma = new PrismaClient({ adapter });
เรื่องที่สอง Prisma เลิกแอบรันคำสั่งให้เองแล้ว เมื่อก่อนตอนติดตั้งแพ็กเกจ ระบบจะรัน prisma generate ให้อัตโนมัติ และตอนสั่ง prisma migrate ก็จะรัน generate กับ seed ให้ด้วย แต่ v7 ตัดพฤติกรรมพวกนี้ออกหมด จากนี้ถ้าอยากให้ generate หรือ seed ทำงาน ต้องสั่งเอง ฟังดูเป็นเรื่องเล็ก แต่ถ้าไม่รู้ไว้ก่อน โค้ดที่เคยรันผ่านอาจพังเงียบ ๆ ตอน deploy ได้
เรื่องที่สาม ถ้าคุณใช้ MongoDB อยู่ ต้องรู้ว่า v7 ยังไม่รองรับ ทาง Prisma จึงแนะนำให้ผู้ใช้ MongoDB อยู่กับ v6 ไปก่อนแล้วรอรุ่นถัดไป ข้อนี้สำคัญมาก เพราะถ้าเผลอย้ายไปแล้วค่อยมารู้ทีหลัง จะย้อนกลับลำบาก
นอกจากสามเรื่องนี้ ยังมีการย้ายค่า config บางอย่างไปไว้ในไฟล์ prisma.config.ts แทนที่จะอยู่ในไฟล์ schema เหมือนเดิม และ Prisma CLI ก็เลิกโหลด environment variable ให้อัตโนมัติ ต้องใช้ไลบรารีอย่าง dotenv มาช่วยแทน ทั้งหมดนี้ไม่ใช่เรื่องยาก แต่เป็นรายละเอียดที่ต้องไล่เก็บให้ครบก่อนนำระบบขึ้น production
ถ้าจะลอง v7 วันนี้ เริ่มจากตรงไหน
ถ้าอยากลองของใหม่โดยไม่ต้องเสี่ยงกับโปรเจกต์จริง วิธีที่ปลอดภัยที่สุดคือเปิดโปรเจกต์ทดลองเล็ก ๆ ขึ้นมาแล้วไล่ทำตามสามขั้นนี้
- เปิดไฟล์ schema.prisma แล้วเปลี่ยนค่า provider ของ generator client จาก prisma-client-js เป็น prisma-client จากนั้นเพิ่มบรรทัด
output = "../src/generated/prisma"เข้าไป - สั่ง prisma generate ด้วยตัวเอง แล้วลองเปิดโฟลเดอร์ src/generated/prisma ดูว่าได้โค้ด client ออกมาจริง
- ในไฟล์ที่สร้าง client เปลี่ยนมา import จาก
./generated/prisma/clientแล้วส่ง driver adapter ตามฐานข้อมูลที่ใช้เข้าไปใน new PrismaClient()
พอสามขั้นนี้ผ่าน คุณจะเห็นภาพทั้งหมดของ v7 ได้ในโปรเจกต์เดียว ทั้งโค้ดที่ย้ายออกมาอยู่ในโปรเจกต์ adapter ที่ต้องต่อ และคำสั่งที่ต้องรันเอง จากนั้นค่อยตัดสินใจว่าจะย้ายโปรเจกต์จริงตามไปเมื่อไร
สิ่งที่ v7 พยายามบอกจริง ๆ
แก่นของ Prisma 7 ไม่ได้อยู่ที่ตัวเลข bundle เล็กลง 90 เปอร์เซ็นต์ หรือ query เร็วขึ้น 3 เท่า ที่ยังรอการพิสูจน์ แต่อยู่ที่ทิศทางของ Prisma เอง เพราะ Prisma กำลังเอาสิ่งที่เคยทำงานอยู่เบื้องหลัง ทั้ง engine ที่ซ่อนอยู่ โค้ดที่ generate ไว้ในที่มองไม่เห็น และคำสั่งที่แอบรันให้เอง ออกมาวางไว้ตรงหน้า แล้วบอกว่าจากนี้เราต้องคุมเอง นั่นคือเหตุผลที่ v7 เบาลงและโปร่งใสขึ้น และก็เป็นเหตุผลเดียวกันที่การอัปเกรดต้องแลกมาด้วยงานที่เราต้องลงมือทำเอง
ที่มา: release notes Release 7.0.0 · prisma/prisma จาก Prisma



