资产编译正在为Webpacker配置文件搜索错误的路径



我已经将webpackergem添加到我的Rails 5.2应用程序中,现在我正尝试将其部署到带有Capistrano的服务器上。进程在deploy:assets:precompile步骤中失败,并显示以下错误消息:

DEBUG [f2c62805] Command: cd /var/www/myapp/releases/20200805023716 && ( export RAILS_ENV="production" RAILS_GROUPS="" ; /usr/local/rvm/bin/rvm 2.5.7 do bundle exec rake assets:precompile )
DEBUG [f2c62805]       Compiling...
DEBUG [f2c62805]       Compilation failed:
webpack config /var/www/myapp/shared/config/webpack/production.js not found, please run 'bundle exec rails webpacker:install' to install Webpacker with default configs or add the missing config file for your custom environment.

我不知道为什么它在shared/config文件夹中查找,而不是在新版本的文件夹中查找。大概我不希望我的配置被共享,以防我更改它并且将来部署失败。在这种情况下,我的应用程序的当前版本会有可能不适合它的配置

以下是一些相关的Capistrano配置:

set :config_files, ['config/boot.rb', 'config/database.yml', 'config/secrets.yml']
set :bin_files, ['bin/bundle', 'bin/delayed_job', 'bin/rails', 'bin/rake', 'bin/webpack']
# Tells Capistrano to store config/database.yml file inside a directory called /shared, which is meant for any files
# we want to persist between deploys
set :linked_files, fetch(:linked_files, []) + fetch(:config_files)
# Directories that are meant to persist between deploys, and they will also be stored inside /shared
set :linked_dirs, fetch(:linked_dirs, []).push('bin', 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')

Sprockets资产编制得很好。我试过在服务器上运行bundle exec rake assets:precompile,它确实在shared/config文件夹中。我运行了一个--trace,发现它运行了webpacker:compile步骤,这就是它失败的地方。

我该怎么做才能让它在当前版本的目录(/var/www/myapp/releases/20200805023716/config/webpack/production.js(中查找配置文件?

我修复了它!有两个问题:
  1. 共享目录中的bin文件
  2. 在预编译资产之前未安装yarn

问题#1:共享目录中的bin文件

我之前已经将部署设置为将bin文件复制到shared目录,以便delayed_job可以运行。上载文件会自动将这些文件设置为可执行文件。到目前为止,这还不是一个问题。但在编译webpack资产时,这是一个问题,因为Webpacker的编译过程中有这样一行:

stdout, stderr, status = Open3.capture3(
webpack_env,
"#{RbConfig.ruby} ./bin/webpack",
chdir: File.expand_path(config.root_path)
)

由于我将所有的bin文件移到了shared目录中,并且Capistrano设置了一个符号链接,因此它将在共享目录中运行bin/webpack文件。当该命令运行时,它会查找Webpacker配置文件的相对路径。给定上下文,这意味着它将在/var/www/myapp/shared/config/webpack/production.js而不是/var/www/myapp/releases/20200805023716/config/webpack/production.js中查找我的webpack配置文件。

解决方案:停止将bin文件复制到shared目录,并将其设置为可执行文件

为了解决此问题,我从Capistrano部署脚本中删除了这一行:

# config/deploy.rb
set :bin_files, ['bin/bundle', 'bin/delayed_job', 'bin/rails', 'bin/rake', 'bin/webpack']

然后我从我的链接目录中删除了bin

# config/deploy.rb
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')

在此之后,Webpacker将在预编译资产时查找正确的目录。现在,我需要解决可执行文件的问题。我添加了一个新的Capistrano任务,我在这个SO答案上找到了它:

before "deploy:symlink:release", "deploy:ensure_bin_files_executable"
namespace :deploy do
desc 'Ensure that bin files are executable'
task :ensure_bin_files_executable do
on roles(:web) do
within release_path do
execute "cd #{release_path} && chmod +x bin/*"
end
end
end
end

这使得当前版本的bin/文件夹中的所有文件都可以执行。问题解决了!

问题2:在预编译资产之前未安装yarn

在解决了第一个问题后,我在预编译资产时收到了这个错误:

01:33 deploy:assets:precompile
01 /usr/local/rvm/bin/rvm default do bundle exec rake assets:precompile
01 Webpacker is installed 🎉 🍰
01 Using /var/www/myapp/releases/20200805023716/config/webpacker.yml file for setting up webpack paths
01 Compiling…
01 Compilation failed:
01 yarn run v1.13.0
01 info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
01
01 warning package.json: No license field
01 error Command "webpack" not found.
解决方案:在预编译资产之前安装yarn包

我意识到yarn没有安装webpack包,所以我在Webpacker部署文档中发现了这个有用的Capistrano任务:

确保在:linked_dirs 中有公共/包和node_modules

append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/packs", ".bundle", "node_modules"

如果将node_modules添加到:linked_dirs,则需要在deploy:assets:precompile之前运行yarn install,因此可以在deploy.rb 底部添加此代码段

before "deploy:assets:precompile", "deploy:yarn_install"
namespace :deploy do
desc "Run rake yarn install"
task :yarn_install do
on roles(:web) do
within release_path do
execute("cd #{release_path} && yarn install --silent --no-progress --no-audit --no-optional")
end
end
end
end

一旦我添加了它,我的部署就顺利了!

最新更新