ajmaleylia

Hi, I'm Ajmal
Tech Consultant

Deploying Ruby on Rails 8 with Node.js on AWS EC2: Lessons Learned from a Painful Asset Precompilation Process

If you’re deploying a Ruby on Rails application on an AWS EC2 instance, you’re likely aware of the various hurdles that can arise during the deployment process. Recently, I embarked on deploying a new application using Ruby 3.4.3, Ruby on Rails 8, Mina/Tomo/Capistrano and Ubuntu on an EC2 instance. What seemed like a straightforward process quickly devolved into a frustrating saga of failed asset precompilation, specifically stalling at rails assets:precompile.

The Trouble Begins: A Stuck Deployment

My deployment consistently ran into a roadblock at asset precompilation, which is a crucial step for any Rails application as it compiles assets like CSS and JavaScript into a single file for optimized delivery. I sought answers from various AI tools like Claude.ai, ChatGPT, and Gemini, but none could pinpoint the issue, which I discovered was related to Node.js, Yarn 4, and esbuild.

Chat Logs from Claude

It became clear that esbuild, a fast bundler and minifier was having trouble building the JavaScript files necessary for my app. I started with a few common fixes. One of the first approaches was to adjust the nodeLinker setting in my Yarn configuration:

echo 'nodeLinker: node-modules' >> .yarnrc.yml

Unfortunately, this did not resolve the issue.

Updating Mina Deployment Configurations

Not one to give up easily, I turned my attention to the Mina deployment tool, which is highly effective for deploying Ruby applications. I updated my config/deploy.rb file, ensuring that Yarn would run before asset precompilation. Here’s how my final configuration looked:

# Ensure yarn install runs before asset precompilation
task :yarn_install do
  command %{cd "#{fetch(:current_path)}" && yarn install --production}
end

task :build do
  command %{cd "#{fetch(:current_path)}" && yarn build}
end

# Add these to your deploy task
task deploy: :remote_environment do
  deploy do
    invoke :'git:clone'
    invoke :'deploy:link_shared_paths'
    invoke :'bundle:install'
    invoke :yarn_install  # Add this
    invoke :build         # Add this
    invoke :'rails:assets_precompile'
    invoke :'deploy:cleanup'
  end
end

However, this change led to a new error:

➤ YN0050: The --production option is deprecated on 'install'; use 'yarn workspaces focus' instead
! ERROR: Deploy failed.

This new hurdle was indeed frustrating, as any update seemed to spawn new issues.

The Solution from Reddit Leads the Way

After spending countless hours pouring over error logs and trying different configurations, I finally stumbled upon a post on the r/rails subreddit. The community member suggested a rather unconventional but straightforward solution: deleting the .pnp.cjs file from my home directory.

This “Plug’n’Play” feature of Yarn can sometimes cause conflicts, especially when not set up completely for certain setups. With bated breath, I executed the command to delete the file, crossed my fingers, and initiated the deployment process once more.

To my amazement, the deployment proceeded past the asset precompilation step without further issues! It was a monumental relief after the frustration of days prior. Happy deploying!

Blog