Rails 构建时下载 importmap 资源的方法
问题
Importmap-rails 默认的加载来源是 CDN,但是公共 CDN 在国内访问不稳定。另一个方法是将 JavaScript 下载到 vender/javascript
目录,但是这个方法需要将外部 JavaScript 签入源码管理工具,导致源码体积变大。
有没有方法可以将下载 JavaScript 延后到构建时执行呢?我经过实践找到了一个方法。
解决
第一步,修改 .gitignore
在 .gitignore
加入以下内容:
/vendor/javascript
这会使 git 忽略 importmap
下载的内容。
第二步,importmap pin {package} --download
在 importmap pin
的时候加上 --download
参数,例如:
bin/importmap pin sortablejs --download
这样会立即下载 sortablejs
的源码,存放到 vendor/javascript
中,同时在 config/importmap.rb
中添加以下内容:
pin "sortablejs" # @1.15.0
这是正常的 importmap 操作,只是不需要提交 js 到源码库,并且用 config/importmap.rb
里的内容作为配置。
第三步,添加 rake task
新建 lib/tasks/importmap.rake
文件,写入以下内容:
require "importmap/npm"
require "importmap/packager"
namespace :importmap do
desc "Download"
task :download do
npm = Importmap::Npm.new
packager = Importmap::Packager.new
packages = npm.packages_with_versions.map { |item| item.join("@") }
imports = packager.import(packages)
imports.each do |package, url|
puts %(Pinning "#{package}" to #{packager.vendor_path}/#{package}.js via download from #{url})
packager.download(package, url)
end
end
end
Rake::Task["assets:precompile"].enhance(["importmap:download"])
这样在执行 bin/rails assets:precompile
的时候,会先执行 bin/rails importmap:download
,该任务会根据 config/importmap.rb
的内容下载 JavaScript。
记得在 Dockerfile
中包含 bin/rails assets:precompile
的步骤,即使没有用到其他构建工具。
第四步,其他配置
在其他脚本里加上 bin/rails importmap:download
,例如在 bin/setup
里面加上:
puts "\n== Importmap download =="
system! "bin/rails importmap:download"
方便搭建开发环境。
总结
本文通过添加一个 rake task 实现了将下载 importmap 资源延迟到构建阶段。这样既能自己掌控 JavaScript 文件的分发方式,又不需要将庞大的外部 JavaScript 文件提交到源码库。
这个脚本没有考虑混合使用 importmap 来源和 JavaScript 依赖非常复杂的情况。