How to use pnpm instead of yarn to compile assets on Rails

นักพัฒนาที่ใช้งาน NodeJS และ npm ย่อมรู้จักกับ node_modules hell เป็นอย่างดี ยิ่งเราติดตั้ง package เยอะเท่าไหร่ขนาดของโฟลเดอร์ node_modules ก็จะยิ่งใหญ่โตตามไปด้วยเท่านั้น ด้วยการจัดการ dependencies ของ npm ซึ่งทำได้ไม่ดีนัก ทำให้มี package management ตัวอื่นๆ ถูกพัฒนาขึ้นมาเพื่อทดแทน

เมื่อเราใช้งาน jsbundling-rails ใน Rails พบว่า package management ที่ถูกผูกไว้ตอน assets:precompile จะเป็น yarn ซึ่งจะเห็นได้จากโค้ด build.rake ดังนั้นถ้าเราต้องการเปลี่ยนไปใช้ pnpm หรือ package management ตัวอื่นเราจำเป็นจะต้อง override task ดังกล่าวดังแสดงในโค้ดด้านล่าง

# lib/tasks/build.rake
namespace :pnpm do
  desc "Build your JavaScript bundle"
  task :build do
    # Using pnpm instead of yarn
    unless system "pnpm install && pnpm run build"
      raise "Command build failed, ensure pnpm is installed and `pnpm run build` runs without errors"
    end
  end
end

  # Clear javascript:build task
Rake::Task["javascript:build"].clear
if Rake::Task.task_defined?("assets:precompile")
  Rake::Task["assets:precompile"].enhance(["pnpm:build"])
end

if Rake::Task.task_defined?("test:prepare")
  Rake::Task["test:prepare"].enhance(["pnpm:build"])
elsif Rake::Task.task_defined?("db:test:prepare")
  Rake::Task["db:test:prepare"].enhance(["pnpm:build"])
end

เพียงเท่านี้เราก็สามารถใช้ pnpm ในการคอมไฟล์ assets ได้แล้วเมื่อเรารันคำสั่ง rails assets:precompile

ตัวอย่างขนาดไฟล์เมื่อใช้ pnpm เปรียบเทียบกับ npm

node_modules จาก npm

node_modules จาก pnpm

จากภาพจเป็นขนาดที่ได้จากการใช้ npm และ pnpm โดยใช้โปรเจ็คเดียวกัน ซึ่งก็จะเห็นได้อย่างชัดเจนว่าขนาดของ node_modules ที่สร้างจาก pnpm มีขนาดเล็กกว่า npm พอสมควร ทั้งนี้ขนาดที่แตกต่างๆ กันก็ขึ้นอยู่กับ package ที่ใช้ว่ามี dependencies ผูกกันมากน้อยเพียงใดด้วย

References