Rails importmap устанавливает скрипты поставщика в vendor/javascript и ожидает, что я проверю этот каталог в системе контроля версий:
Пакеты загружаются в
vendor/javascript, их можно проверить в системе управления версиями, и они будут доступны через собственный конвейер ресурсов вашего приложения.
Но я не хочу возвращать эти файлы. Я хочу gitignore их, как вы обычно делаете с чем-то вроде NPM и каталогом node_modules, и поручить своей производственной среде (Heroku) самостоятельно установить эти зависимости. В идеале использовать что-то, что я могу поместить в свой Procfile.
Как мне это сделать? Есть только одна рейковая задача — установка самого importmap, а не зависимостей. Я тоже проверил команды.
Возможно, я мог бы собрать что-то вместе, которое перебирало бы зависимости и загружало их по отдельности, но обычно менеджеры пакетов предлагают для этого уже существующий общедоступный API, поэтому я уверен, что просто что-то упускаю.





Вы ничего не упускаете, команды переустановки нет. Я взял код из этого отклоненного запроса на включение:
https://github.com/rails/importmap-rails/pull/226
Мне пришлось проявить творческий подход, чтобы воплотить это в патче, потому что команды выполняются сразу после определения класса:
# config/application.rb
def Importmap.const_added(const_name)
if const_name == :Commands
Importmap::Commands.class_eval do
desc "redownload", "Force download every package, even if the required versions are already downloaded"
def redownload
packages = npm.packages_with_versions.map { |package| package.join("@") }
pin packages
end
end
end
end
$ bin/importmap redownload
Pinning "@popperjs/core" to vendor/javascript/@popperjs/core.js via download from https://ga.jspm.io/npm:@popperjs/[email protected]/lib/index.js
Pinning "bootstrap" to vendor/javascript/bootstrap.js via download from https://ga.jspm.io/npm:[email protected]/dist/js/bootstrap.esm.js
Обновлять
Если у вас есть пакеты, прикрепленные к URL-адресам, вы можете просто начать загружать их вместо этого, что является поведением по умолчанию в importmap-rails v2, в противном случае вам придется выполнить некоторую ручную работу:
def redownload
# packages = npm.packages_with_versions.map { |package| package.join("@") }
packages = npm.send(:importmap).scan(/^pin ["']([^["']]*)["'].* #.*@(\d+\.\d+\.\d+(?:[^\s]*)).*$/).map{_1*"@"}
pin packages
end
https://github.com/rails/importmap-rails/blob/v2.0.1/lib/importmap/npm.rb#L52
Обновление №2
Похоже источник скачивания нигде не отслеживается. Я только что проверил команду bin/importmap update, и она также игнорирует исходный источник и использует jspm, что мне кажется ошибкой.
Этот немного сложнее. Во-первых, добавьте возможность отслеживать первоисточник:
# config/application.rb
require "importmap/packager"
Importmap::Packager.class_eval do
# https://github.com/rails/importmap-rails/blob/v2.0.1/lib/importmap/packager.rb#L39
def vendored_pin_for(package, url)
filename = package_filename(package)
version = extract_package_version_from(url)
vendor = url.match(/npm|skypack|unpkg|jsdelivr/) # <= this
if "#{package}.js" == filename
%(pin "#{package}" # #{version} #{vendor}).strip
else
%(pin "#{package}", to: "#{filename}" # #{version} #{vendor}).strip
end
end
end
если ты прикрепишь imask:
bin/importmap pin imask --from unpkg
вы получите вот такую булавку:
pin "imask" # @7.6.1 unpkg
Теперь проанализируйте эту карту импорта и используйте unpkg в качестве опции --from:
# config/application.rb
def Importmap.const_added(const_name)
if const_name == :Commands
Importmap::Commands.class_eval do
desc "redownload", "Force download every package, even if the required versions are already downloaded"
def redownload
# adjusted here vvvvvvv
npm.send(:importmap).scan(/^pin ["']([^["']]*)["'].* #.*@(\d+\.\d+\.\d+(?:[^\s]*)).*?(\w+)?$/).group_by { _3 }.each do |from, packages|
packages_with_version = packages.map do |package|
package.pop
package * "@"
end
@options = {from:}
pin packages_with_version
end
end
end
end
end
Тест:
# config/importmap.rb
pin "bootstrap" # @5.3.3
pin "@popperjs/core", to: "@popperjs--core.js" # @2.11.8
pin "jquery" # @3.7.1 jsdelivr
pin "imask" # @7.6.1 unpkg
$ bin/importmap redownload
Pinning "@popperjs/core" to vendor/javascript/@popperjs/core.js via download from https://ga.jspm.io/npm:@popperjs/[email protected]/lib/index.js
Pinning "bootstrap" to vendor/javascript/bootstrap.js via download from https://ga.jspm.io/npm:[email protected]/dist/js/bootstrap.esm.js
Pinning "jquery" to vendor/javascript/jquery.js via download from https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.js
Pinning "imask" to vendor/javascript/imask.js via download from https://unpkg.com/[email protected]/esm/index.js
К сожалению, это не очень хорошо работает с пакетами, прикрепленными к пользовательским URL-адресам. В конечном итоге он загружает ненужные файлы JS. @Алекс
Ты какой-то волшебник. Но, как вы знаете, скачать их не всегда получается. Например, pin 'imask', to: 'https://unpkg.com/[email protected]/dist/imask.js' в конечном итоге загружает другой файл из другого источника. Поэтому я думаю, что ваш подход с регулярным выражением лучше.
@DennisHackethal см. обновление № 2
Спасибо. Запуск этого как части веб-динамо Heroku работает хорошо:
bin/importmap redownload && bin/rails server -p ${PORT:-5000} -e $RAILS_ENV