Read more

Configuring Webpacker deployments with Capistrano

Dominik Schöler
December 09, 2020Software engineer at makandra GmbH

When deploying a Rails application that is using Webpacker and Capistrano, there are a few configuration tweaks that optimize the experience.

Using capistrano-rails

Illustration online protection

Rails Long Term Support

Rails LTS provides security patches for old versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2)

  • Prevents you from data breaches and liability risks
  • Upgrade at your own pace
  • Works with modern Rubies
Read more Show archive.org snapshot

capistrano-rails Show archive.org snapshot is a Gem that adds Rails specifics to Capistrano, i.e. support for Bundler, assets, and migrations. While it is designed for Asset Pipeline (Sprockets) assets, it can easily be configured for Webpacker. This brings these features to the Webpacker world:

  • Automatic removal of expired assets
  • Manifest backups
# config/deploy.rb

# No need to include public/packs here, but add the Webpacker cache dir (see link below)
set :linked_dirs, %w[… tmp/cache/webpacker]

# capistrano-rails config
set :assets_roles, %i[webpack] # Give the webpack role to a single server  (see code block below)
set :assets_prefix, 'packs' # Assets are located in /packs/
set :keep_assets, 10 # Automatically remove stale assets
set :assets_manifests, lambda { # Tell Capistrano-Rails how to find the Webpacker manifests
  [release_path.join('public', fetch(:assets_prefix), 'manifest.json*')]
}

set :conditionally_migrate, true # Only attempt migration if db/migrate changed - not related to Webpacker, but a nice thing

Give the webpack role to a single server:

#  config/deploy/production.rb (analog to config/deploy/staging.rb)
...

server '<server url>', user: '<user name>', roles: %w(... webpack) 

Make sure to read as well:

Only compiling production packs on the server

Asset compilation takes quite some time, and slows down deployments. Let's only compile packs that are relevant, then. No need for specs and other development packs on the servers.

Create a directory "packs_production" right next to your "packs" directory. Next, symlink all packs that are required in production:

app/
  ...
  webpack/
    packs/
      app/
      test/
    packs_production
      app -> ../packs/app

Now tell Webpacker to use these for production (and staging):

# config/webpacker.yml

production: &production
  <<: *default
  # Only compile relevant packs
  source_entry_path: packs_production
  ...

staging: *production

Disabling unused compression

Webpacker supports Brotli Show archive.org snapshot compression, and produces .br files whenever compiling zipped files. However, these are of no value when they are not used.

To prevent the generation of Brotli files:

# config/webpack/environment.js
const webpackConfig = environment.toWebpackConfig()

// Save compile time by disabling an unused compression
webpackConfig.plugins = webpackConfig.plugins.filter(plugin => {
  const isBrotliCompression = plugin.constructor.name === 'CompressionPlugin' && plugin.options.algorithm === 'brotliCompress'
  return !isBrotliCompression
})

Older Webpacker versions might need this instead:

// Save compile time by disabling an unused compression
if (environment.plugins.getIndex('Compression Brotli') >= 0) {
  environment.plugins.delete('Compression Brotli')
}
Dominik Schöler
December 09, 2020Software engineer at makandra GmbH
Posted by Dominik Schöler to makandra dev (2020-12-09 13:12)