updated at: 26 Nov 2023
บล็อกนี้ไม่ได้จะมาตีเลขหวยนะครับ บอกเผื่อไว้ก่อน!
"0.1.12", "1.6.3", "2.0.0-alpha.1", "2.0.0-beta.1.5.1+12553"... หลาย ๆคนคงเคยเห็นเลขเวอร์ชันหน้าตาประมาณนี้กันมาอยู่แล้ว แต่บางคนก็อาจจะไม่รู้ว่าทำไมมันถึงต้องเขียนแบบนั้น มันหมายความว่าอย่างไร ทำไมเขียนแค่ตัวเลขอย่างเดียวเช่น เวอร์ชัน 1, เวอร์ชัน 25, เวอร์ชัน 36 ฯลฯ ถึงไม่เพียงพอ ตัวเลขหน้าตาแบบนี้ มันเรียกว่า "Semantic Versioning" ซึ่งเป็นชุดตัวเลขและตัวอักษรที่หากเราเข้าใจมัน เราก็จะเข้าใจได้ว่า เวอร์ชันนั้น ๆเป็นเวอร์ชันที่มีการอัพเดทในลักษณะใด ทำให้เราสามารถเลือกใช้งานหรืออัพเดทซอฟต์แวร์ได้อย่างถูกต้อง รวมถึงว่าหากเราจะทำซอฟต์แวร์ขึ้นมาให้ผู้พัฒนาคนอื่นได้ใช้งาน เราก็ควรที่จะต้องเขียนเวอร์ชันให้ถูกต้องตามมาตรฐาน
โครงสร้างของ Semantic Versioning นั้นจะประกอบไปด้วย
หลังจากที่เรารู้แล้วว่ามันประกอบไปด้วยอะไรบ้าง และแต่ละอย่างมันหมายความว่าอย่างไรแล้ว ถัดมันเราก็ต้องรู้วิธีเขียนมันให้ถูกต้องตามโครงสร้าง
*สำหรับ pre-release version ที่มีเครื่องหมาย "." คั่นนั้น จะเรียกพวกตัวเลขหรือตัวอักษรที่ถูกคั่นว่า "Identifier" เช่น 1.0.0-alpha-1.3.0 จะมี Identifier ของ pre-release version ได้แก่ alpha-1, 3 และ 0
สามารถอ่านกฎฉบับเต็มได้ ที่นี่
แน่นอนว่าเมื่อเป็นเรื่องของเวอร์ช ัน มันต้องมีลำดับก่อนหลังของแต่ละเวอร์ชัน สำหรับ Semantic Versioning นั้นจะมีวิธีการเรียงลำดับดังนี้
ตัวอย่างการเรียงลำดับ: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0
*Note: จะมีเวอร์ชันอยู่รูปแบบหนึ่งซึ่งมักจะใช้กับซอฟต์แวร์ที่เพิ่งเปิดให้ใช้งาน ในช่วงนี้ซอฟต์แวร์จะมีการอัพเดทค่อนข้างบ่อย อาจจะมีการเปลี่ยนแปลงระหว่างเวอร์ชันค่อนข้างมาก เขาก็จะใช้เวอร์ชันเป็น "0.x.x" เพื่อบอกว่าซอฟต์แวร์ตัวนั้น ๆยังอยู่ในสถานะเริ่มต้น อาจจะยังไม่เสถียรและยังไม่แนะนำให้ใช้กับ production... (Fun Fact: React Native ที่คนใช้เขียนแอพขึ้น production มากันเต็มไปหมด จริ ง ๆแล้วยังเป็นเวอร์ชัน 0.x.x อยู่ 😂😂😂)
สามารถอ่านกฎการเรียงลำดับจากต้นฉบับได้ ที่นี่
พวก Package Managers หลาย ๆเจ้านั้นก็ได้มีการทำ Semantic Versioning มาใช้ ซึ่งเมื่อเราใช้งานเราสามารถกำหนดได้ว่าแพ็จเกจไหนจะเป็นเวอร์ชันอะไรตามหลักของ Semantic Versioning ผมจะขอยกตัวอย่างจาก NPM ซึ่งน่าจะเป็นตัวที่ค่อนข้างนิยมและหลาย ๆคนน่าจะเคยใช้งานกัน
"dependencies": {
"my_dep_1": "1.0.0",
"my_dep_2": "~2.2.0",
"my_dep_3": "^2.2.0",
"my_dep_4": "~3.0.0-alpha.1.1.0",
"my_dep_5": "^4.0.0-beta.1.0.4"
},
จากตัวอย่างข้างบน จะเห็นว่าบางแพ็กเกจมันมีสัญลักษณ์ caret (^) หรือ tilde (~) อยู่ข้างหน้าเวอร์ชัน
npm install
เช่น
"dependencies": {
"my_dep_3": "^2.2.0"
}
เมื่อ my_dep_3
มีการ publish เวอร์ชัน "2.2.1" หรือ "2.3.0" มา npm ก็จะทำการติดตั้งเวอร์ชันพวกนั้นให้เราเมื่อเราทำการสั่ง npm install
npm install
เช่น
"dependencies": {
"my_dep_2": "~2.2.0"
}
เมื่อ my_dep_2
มีการ publish เวอร์ชัน "2.2.1" มา npm ก็จะทำการติดตั้งเวอร์ชันพวกนั้นให้เราเมื่อเราทำการสั่ง npm install
แต่ถ้ามีการ publish เวอร์ชัน "2.3.0" มา มันก็จะไม่สนใจ เพราะ tilde จะสนใจแค่ patch version เท่านั้น
*เสริม: สำหรับ pre-release version นั้น มันจะไม่ถูกติดตั้งมาให้อัตโนมัติ เช่น
"dependencies": {
"my_dep_2": "~2.2.0",
"my_dep_3": "^2.2.0"
}
เมื่อ my_dep_2
หรือ my_dep_3
มีการ publish เวอร์ชัน "2.3.0-beta.1" มา npm ก็จะยังคงติดตั้เวอร์ชัน "2.2.0" มาให้เรา โดยไม่มองว่า "2.3.0-beta.1" เป็นเวอร์ชันใหม่
แต่ ๆ ๆ ถ้าเกิดเราเขียนแบบนี้
"dependencies": {
"my_dep_4": "~3.0.0-alpha.1.1.0"
}
ถ้าเกิดว่า my_dep_4
มีการ publish เวอร์ชัน "3.0.0-alpha.1.1.1" หรือ "3.0.0-alpha.1.2.0" หรือ "3.0.1" มา เมื่อเราสั่ง npm install
ตัว NPM ก็จะติดตั้งเวอร์ชันนั้น ๆให้เรา
ด้วยความที่เราสามารถกำหนดเวอร์ชันของแพ็กเกจแบบ dynamic ได้แบบนี้ มันก็มีทั้งข้อดีและข้อเสียตามมา
npm install
ไม่ต้องคอยติดตามและทำการอัพเดทเวอร์ชันใหม่เองด้วยความที่มันมีทั้งข้อดีและข้อเสีย ดังนั้นจึงอยากให้ทุกคนใช้งานมันด้วยความเข้าใจครับ
*FYI: สำหรับ NPM นั้น เราสามารถดูว่าแพ็กเกจต่าง ๆที่เราใช้งานนั้น จริง ๆแล้วมันถูกติดตั้งเวอร์ชันอะไรมาให้เราได้ที่ไฟล์ package-lock.json
ซึ่งมันจะบอกเลขเวอร์ชันแบบเป๊ะ ๆของแต่ละแพ็กเกจ รวมถึงว่าแต่ละอันมันมีการใช้งานแพ็กเกจอื่น ๆอะไรบ้างและเป็นเวอร์ชันอะไรด้วย ดังนั้น เราสามารถใช้ไฟล์นี้เป็นส่วนหนึ่งในการตรวจสอบเมื่อมีความผิดพลาดอะไรบางอย่างเกิดขึ้นได้ และสามารถใช้ทำเรื่อง Dependency Caching ได้เหมือนกัน ซึ่งไว้เดี๋ยวผมอาจจะหยิบเรื่องนี้มาเล่าในบล็อกถัด ๆไป
ทั้งหมดนี้เป็นความหมายและหลักการของ Semantic Versioning รวมถึงวิธีการกำหนดเวอร์ชันให้แพ็กเกจที่จะใช้งาน เมื่อเราเข้าใจเข้าใจมันแล้ว เราก็จะสามารถที่จะเลือกใช้งานแพ็กเกจได้อย่างถูกต้อง รวมถึงเมื่อซอฟต์แวร์ของเรามีปัญหา เราก็จะได้ตรวจสอบได้ง่ายขึ้นรวมถึงได้ความฉุกคิดเพิ่มอีกอย่างก็คือ "เป็ นเพราะไอ้ ... มันถูกอัพเวอร์ชันรึป่าววะ!"