Rails Rails 构建时下载 importmap 资源的方法

Rei · 2023年11月06日 · 最后由 zhugexinxin 回复于 2024年01月30日 · 842 次阅读

原文链接:https://geeknote.net/Rei/posts/2559

问题

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 依赖非常复杂的情况。

其实我倒是觉得 pin 加上--download 将 js 静态的提交到 vendors 没太大问题 下载的代码都是压缩过的

主要是国内现有网络条件下有时候并不能保证部署机能够 ready to download those js files,

不如砍掉这个依赖,在开发的时候就确定好。

jicheng1014 回复

我有个文件(emoji data)高达 418 k……

构建机放境外解决大部分网络问题。

前台加载的时候一次性一大堆 js,这个 Importmap 加载 js 能不能按照 layout 进行分组?

Rei 回复

谢谢👍

https://github.com/rails/importmap-rails/issues/65 js 中依赖库很多的有上面这种问题,有遇到过吗?

chinacheng 回复

我依赖的库中没有遇到。

Rei 回复

bin/rails assets:precompile 有没有遇到部署后,js 和 css 文件上传后也会显示加载失败。

bin/rails assets:precompile 编译后文件会在 app/assets/builds 和 pubilc 下生成打包文件。

然后我再用 scp 上传这些文件,重启 rails s,奇怪的是没有首页 js 这些就加载失败了,后续我会提供日志图片。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号