ปกติเรารัน npm install vite หรือ npm update ก็ได้เวอร์ชันล่าสุดทันที รวมถึงเวอร์ชันที่เพิ่งออกเมื่อสิบนาทีก่อนด้วย เมื่อ ก.ย. 2568 package ที่คนใช้กันมากอย่าง chalk และ debug มีเวอร์ชันอันตรายออกมาจากบัญชีของคนดูแลที่โดน phishing เวอร์ชันพวกนั้นอยู่บน npm ราวสองชั่วโมงก่อนมีคนเอาออก ใครที่ติดตั้งในช่วงนั้นก็ได้ของอันตรายไปเต็ม ๆ
cooldown คือการรอให้เวอร์ชันใหม่ผ่านไปสักพัก
package ที่โดนแอบใส่โค้ดอันตรายมักโดนจับได้เร็ว บางตัวไม่กี่นาที บางตัวเป็นชั่วโมงหรือเป็นวัน แล้ว registry ก็ถอดเวอร์ชันนั้นออก ถ้าเราไม่รีบหยิบเวอร์ชันที่เพิ่งออก เวอร์ชันอันตรายก็มีโอกาสหายไปก่อนถึงเครื่องเรา
ตัวจัดการ package เรียกเรื่องนี้ต่างกัน cooldown บ้าง minimum release age บ้าง แต่ทำแบบเดียวกันคือข้ามเวอร์ชันที่ออกมายังไม่ครบเวลาที่ตั้งไว้ ฝั่ง PHP ก็มีแล้วตั้งแต่ Composer 2.11 ถ้าใช้ Laravel คู่กับ npm ลองอ่านวิธีตั้ง Composer ให้รอเวอร์ชันใหม่สักพักก่อนติดตั้ง ไปด้วยได้ครับ
ตั้ง min-release-age ใน .npmrc
npm เพิ่ม min-release-age มาตั้งแต่ npm 11.10 (ก.พ. 2569) และยังปิดไว้เป็นค่าเริ่มต้น ใส่ไว้ใน .npmrc ที่รากโปรเจกต์แล้ว commit ไปพร้อมโค้ด ทุกคนในทีมจะได้ค่าเดียวกัน
min-release-age=1
min-release-ageนับเป็นจำนวนวันเท่านั้น เขียนหน่วยแบบ"1 day"ไม่ได้- ถ้าอยากให้มีผลทุกโปรเจกต์บนเครื่อง ใช้
npm config set min-release-age 1 --location=userแทน
npm ที่ต่ำกว่า 11.10 ไม่รู้จัก setting นี้ ตั้งไว้ก็ไม่มีผล เช็คด้วย npm --version ถ้ายังเป็นรุ่นเก่า อัปเดตได้ด้วย npm install -g npm@11 (รุ่น 11 ล่าสุดใช้กับ Node 20.17 และ 22.9 ขึ้นไป)
npm มาพร้อม Node.js ถ้า Node ในเครื่องเก่าจนลง npm 11 ไม่ได้ ก็ถึงเวลาขยับ Node ด้วย เช็คได้ที่Node.js ที่ใช้อยู่เก่าแค่ไหน ว่ารุ่นที่ใช้ยังได้อัปเดตไหม และถ้าต้องมีหลายรุ่นในเครื่อง ลองใช้ nvm สลับทีละโปรเจกต์ได้
ยกเว้น package ของเราเองหรือตอนต้องรีบแพตช์
package ที่เราดูแลเองไม่จำเป็นต้องรอ ใส่ชื่อหรือ pattern ไว้ใน min-release-age-exclude ซึ่งใช้ได้ตั้งแต่ npm 11.17
min-release-age=1
min-release-age-exclude[]=@myorg/*
min-release-age-exclude[]=my-internal-pkg
npm ยกเว้นเฉพาะตัวที่ระบุ ส่วน dependency ของ package นั้นยังต้องรอเหมือนเดิม ถ้าไม่ได้ใส่ pattern ให้ตรงด้วย
แพตช์ความปลอดภัยต้องรอ cooldown เหมือนเวอร์ชันอื่น วันที่ package ที่ใช้อยู่มีช่องโหว่ใหญ่ เราจึงต้องข้ามเองทีละครั้ง
npm install vite@latest --min-release-age=0
npm 11.19 ขึ้นไป ถ้า cooldown ทำให้ npm audit fix ลงเวอร์ชันที่แก้ช่องโหว่ไม่ได้ npm จะคง package ไว้ที่เวอร์ชันเดิม เตือนว่าแพตช์ยังไม่ครบเวลา และจบคำสั่งด้วย error เราจะได้รู้ว่ายังมีช่องโหว่ค้างอยู่ แล้วเลือกเองว่าจะรอหรือข้ามด้วยคำสั่งข้างบน
cooldown ทำงานตอนเลือกเวอร์ชัน ไม่ใช่ตอน deploy
| คำสั่ง | cooldown มีผลไหม |
|---|---|
npm install <package>, npm update |
มีผล ข้ามเวอร์ชันที่ยังไม่ครบเวลา ถ้าไม่มีเวอร์ชันไหนผ่านเกณฑ์เลย คำสั่งจะ error |
npm ci |
ไม่มีผล ติดตั้งตาม package-lock.json ทุกตัว |
npm outdated |
นับเฉพาะเวอร์ชันที่ผ่านช่วงรอแล้ว |
ขั้น deploy และ CI ที่รัน npm ci จึงไม่เปลี่ยนอะไร จุดที่ cooldown ช่วยคือตอนที่เราเพิ่มหรืออัปเดต package บนเครื่องตัวเองแล้ว commit package-lock.json ขึ้นไป
ถ้าเคยตั้ง before ไว้ ซึ่งรับเป็นวันที่ตายตัว ให้เลือกใช้อย่างใดอย่างหนึ่ง npm 11 ไม่ยอมให้ตั้งคู่กัน
pnpm, Yarn และ Bun ใช้หน่วยไม่เหมือนกัน
ตัวจัดการ package ฝั่ง JavaScript ตัวอื่นก็มี setting แบบเดียวกัน แต่ชื่อและหน่วยต่างกันหมด ตั้งให้รอหนึ่งวันได้แบบนี้
| ตัวจัดการ package | ไฟล์ | รอหนึ่งวัน | ยกเว้นด้วย |
|---|---|---|---|
| npm | .npmrc |
min-release-age=1 (วัน) |
min-release-age-exclude |
| pnpm | pnpm-workspace.yaml |
minimumReleaseAge: 1440 (นาที) |
minimumReleaseAgeExclude |
| Yarn | .yarnrc.yml |
npmMinimalAgeGate: "1d" |
npmPreapprovedPackages |
| Bun | bunfig.toml ใต้ [install] |
minimumReleaseAge = 86400 (วินาที) |
minimumReleaseAgeExcludes |
pnpm รุ่นปัจจุบันตั้ง minimumReleaseAge ไว้ที่ 1440 นาทีเป็นค่าเริ่มต้นอยู่แล้ว ถ้าใช้ pnpm รุ่นเก่ากว่านั้นหรือตัวอื่น ลองเช็คในเอกสารของแต่ละตัวว่ารุ่นที่ใช้อยู่รองรับหรือยัง
ให้ bot เปิด PR อัปเดตหลังพ้น cooldown
cooldown ใน .npmrc ช่วยตอนที่เรา update เอง ถ้าอยากให้มีคนบอกว่ามีเวอร์ชันใหม่ที่ผ่านช่วงรอแล้ว ก็ให้ bot ทำ Dependabot รอให้เวอร์ชันใหม่ออกมาครบ 3 วันก่อนเปิด PR อยู่แล้ว และปรับเวลารอได้ด้วย cooldown ใน .github/dependabot.yml
version: 2
updates:
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
cooldown:
default-days: 3
semver-major-days: 14
exclude:
- '@myorg/*'
default-daysคือจำนวนวันที่รอสำหรับทุก package ไม่ใส่ก็เป็น 3 วันsemver-major-daysให้เวอร์ชัน major รอนานกว่า เพราะมักมี breaking change และแพตช์แก้ตามมา ตั้งsemver-minor-daysกับsemver-patch-daysแยกได้เหมือนกันexcludeใส่ package ที่ไม่ต้องรอ ใช้*ได้
โปรเจกต์ที่มี Composer ด้วยก็ใส่ cooldown ชุดเดียวกันไว้ใน block ของ package-ecosystem: composer ส่วน security updates ของ Dependabot ไม่รอ cooldown เปิด PR แพตช์ให้ทันทีที่มี advisory
ถ้าใช้ Renovate ตั้ง minimumReleaseAge เป็น "3 days" คู่กับ internalChecksFilter: "strict" แล้ว Renovate จะยังไม่เปิด PR จนกว่าจะมีเวอร์ชันที่ผ่านช่วงรอครับ






