Как добавить собственный JS-файл в новый проект rails 7
Я создал новый проект rails 7
rails new my_project
и у меня проблема с включением моего пользовательского файла JS в обработанный рельсами.
мой "javascript / application.js"
import "@hotwired/turbo-rails"
import "controllers"
import "chartkick"
import "Chart.bundle"
import "custom/uni_toggle"
мой собственный файл JS: "javascript / custom / uni_toggle.js"
function uniToggleShow() {
document.querySelectorAll(".uni-toggle").forEach(e => e.classList.remove("hidden"))
}
function uniToggleHide() {
console.log("uni toggle hide")
document.querySelectorAll(".uni-toggle").forEach(e => e.classList.add("hidden"))
}
window.uniToggleShow = uniToggleShow
window.uniToggleHide = uniToggleHide
Я использую в своем макете
<%= javascript_importmap_tags %>
и мой "confing / importmap.rb"
pin "application", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin_all_from "app/javascript/controllers", under: "controllers"
4 ответа
Допустим, мы добавили каталог плагинов :
app/
└── javascript/
├── application.js # <= imports go here
└── plugin/
├── app.js
└── index.js
config/
└── importmap.rb # <= pins go here
Закрепить один файл:
# config/importmap.rb
pin "plugin/app"
pin "plugin/index"
# app/javascript/application.js
import "plugin/app"
import "plugin/index"
или закрепите все файлы в каталоге плагина и подкаталогах:
# config/importmap.rb
pin_all_from "app/javascript/plugin", under: "plugin"
# app/javascript/application.js
import "plugin/app"
import "plugin"
Не используйте относительный импорт, напримерimport "./plugin"
, он может работать в разработке, но сломается в производстве.
См. выводbin/importmap json
чтобы знать, что вы можете импортировать.
Не выполняйте предварительную компиляцию в процессе разработки, он будет обслуживать предварительно скомпилированные активы изpublic/assets
которые не обновляются при внесении изменений.
Бегатьbin/rails assets:clobber
для удаления предварительно скомпилированных ресурсов.
В случае, если что-то не работает, каталог app/javascript должен находиться в:
Rails.application.config.assets.paths
иapp/assets/config/manifest.js
//= дерево_ссылок ../../javascript .js
Закрепление ваших файлов не приводит к их загрузке. Они должны быть импортированы в:
// app/javascript/application.js
import "plugin"
В качестве альтернативы, если вы хотите разделить свой пакет, вы можете использовать отдельный тег модуля в своем макете:
<%= javascript_import_module_tag "plugin" %>
или шаблоны:
<% content_for :head do %>
<%= javascript_import_module_tag "plugin" %>
<% end %>
# add this to the end of the <head> tag:
# <%= yield :head %>
Вы также можете добавить еще одну точку входа в дополнение кapplication.js
, скажем, вы добавилиapp/javascript/admin.js
. Вы можете импортировать его со всеми выводами:
# this doesn't load application.js anymore
<%= javascript_importmap_tags "admin" %>
Кажетсяpin_all_from
не получил никакой документации, кроме того, что она есть в importmap.rb по умолчанию .
pin_all_from (каталог, под: ноль, в: ноль, предварительная загрузка: ложь)
https://github.com/rails/importmap-rails/blob/v1.1.2/lib/importmap/map.rb#L33
def pin_all_from(dir, under: nil, to: nil, preload: false)
clear_cache
@directories[dir] = MappedDir.new(dir: dir, under: under, path: to, preload: preload)
end
dir
- Путь относительно Rails.root или абсолютный путь.
Параметры:
:under
- Необязательный префикс булавки. Обязательно, если у вас естьindex.js
файл.
- Необязательный путь к активу. Возвращается к опции : under . Требуется, если :under опущен. Этот путь относится к Rails.application.config.assets.paths .
- Добавляет ссылку на предварительную загрузку модуля , если установлено:
<link rel="modulepreload" href="/assets/turbo-5605bff731621f9ca32b71f5270be7faa9ccb0c7c810187880b97e74175d85e2.js">
Мы можем закрепить все файлы в каталоге плагина :
pin_all_from "app/javascript/plugin", under: "plugin"
# NOTE: `index.js` file gets a special treatment, instead
# of pinning `plugin/index` it is just `plugin`.
{
"imports": {
"plugin/app": "/assets/plugin/app-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js",
"plugin": "/assets/plugin/index-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js"
}
}
Вот как все это сочетается:
"plugin/app": "/assets/plugin/app-04024382391bb...4145d8113cf788597.js"
# ^ ^ ^
# | | |
# :under | `-path_to_asset("plugin/app.js")
# | ^ ^
# | | |
# |.. (:to||:under)-' |
# "#{dir}/app.js" |
# '''''`-------------------------'
здесь вариант может быть неочевидным. Полезно, если опция :under изменена, что сделаетpath_to_asset
не удается найти app.js.
Например, опция :under может быть чем угодно, но опция :to должна быть путем, который конвейер ресурсов, Sprockets , может найти (см. Rails.application.config.assets.paths ), а также предварительно скомпилировать (см. app/assets/ config/manifest.js ).
pin_all_from "app/javascript/plugin", under: "@plug", to: "plugin"
# Outputs these pins
#
# "@plug/app": "/assets/plugin/app-04024382391b1...16beb14ce788597.js"
# "@plug": "/assets/plugin/index-04024382391bb91...4ebeb14ce788597.js"
#
# and can be used like this
#
# import "@plug";
# import "@plug/app";
Указание абсолютного пути приведет к обходу конвейера ресурсов.
pin_all_from("app/javascript/plugin", under: "plugin", to: "/plugin")
# "plugin/app": "/plugin/app.js"
# "plugin": "/plugin/index.js"
#
# NOTE: It is up to you to set up `/plugin/*` route and serve these files.
Чтобы закрепить один файл, используйтеpin
метод.
вывод (имя, до: ноль, предварительная загрузка: ложь)
https://github.com/rails/importmap-rails/blob/v1.1.2/lib/importmap/map.rb#L28
def pin(name, to: nil, preload: false)
clear_cache
@packages[name] = MappedFile.new(name: name, path: to || "#{name}.js", preload: preload)
end
name
- Название булавки.
Параметры:
- Необязательный путь к активу. Отступает к{name}.js
. Этот путь относится к Rails.application.config.assets.paths .
:preload
- Добавляет ссылку на предварительную загрузку модуля , если установлено значениеtrue
При закреплении локального файла укажите имя относительно каталога app/javascript .
pin("plugin/app")
pin("plugin/index")
# NOTE: produces these pins
{
"imports": {
"plugin/app": "/assets/plugin/app-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js",
"plugin/index": "/assets/plugin/index-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js"
}
}
Вот как это сочетается:
"plugin/app": "/assets/plugin/app-04024382391bb...16cebeb14ce788597.js"
# ^ ^
# | |
# name `-path_to_asset("plugin/app.js")
# ^
# |
# (:to||"#{name}.js")-'
Если вы хотите изменить название пин-кода,:to
требуется, чтобы указать path_to_asset действительное расположение файла.
Например, чтобы получить тот же пин для файла index.js , который мы получаем из pin_all_from :
pin("plugin", to: "plugin/index")
{
"imports": {
"plugin": "/assets/plugin/index-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js"
}
}
Вы можете возиться сImportmap
в консоли быстрее отлаживать и узнавать, что работает, а что нет:
>> map = Importmap::Map.new
>> map.pin_all_from("app/javascript/plugin", under: "plugin")
# NOTE: ApplicationController has the required `path_to_asset` helper
>> ApplicationController.helpers.path_to_asset("plugin/app.js")
=> "/assets/plugin/app-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js"
# NOTE: `path_to_asset` searches relative to these paths
>> Rails.application.config.assets.paths
>> puts map.to_json(resolver: ApplicationController.helpers)
{
"imports": {
"plugin/app": "/assets/plugin/app-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js",
"plugin": "/assets/plugin/index-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js"
}
}
# `pin` seems so much simpler now
>> map.pin("application")
>> puts map.to_json(resolver: ApplicationController.helpers)
{
"imports": {
"application": "/assets/application-8cab2d9024ef6f21fd55792af40001fd4ee1b72b8b7e14743452fab1348b4f5a.js"
}
}
# Importmap from config/importmap.rb
>> Rails.application.importmap
Относительный/абсолютный импорт может работать, если вы сделаете правильное сопоставление:
# config/importmap.rb
pin "/assets/plugin/app", to: "plugin/app.js"
// app/javascript/application.js
import "./plugin/app"
application.js сопоставляется с дайджестом /assets/application-123.js, потому что./plugin/app
относится к /assets/application-123.js, он должен быть правильно разрешен к/assets/plugin/app
у которого есть карта импорта, которую мы сделали с помощью нашего пин-кода:
"/assets/plugin/app": "/assets/plugin/app-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js",
Это также должно работать:
// app/javascript/plugin/index.js
import "./app"
Однако покаimport-maps
поддерживает весь относительный и абсолютный импорт, это не похоже на предполагаемый вариант использования вimportmap-rails
.
Также возникли проблемы с добавлением пользовательских файлов JS в мое приложение Rails 7. Я даже следил за видео DHH --> https://www.youtube.com/watch?v=PtxZvFnL2i0 , но все еще сталкивался с трудностями. Следующие шаги работали для меня:
- Перейдите в config/importmap.rb и добавьте следующее:pin_all_from "app/javascript/custom", в разделе: "custom"
- Перейдите в файл app/javascript/application.js и добавьте следующее: import "custom/main"
- В каталоге app/javascript добавьте папку custom.
- В каталог app/javascript/custom добавьте свой пользовательский файл js main.js.
- Запустите в своем терминале: rails assets:precompile
- Запустите свой сервер rails. Вуаля
После просмотра видео DHH я нашел последний кусочек головоломки.
Чтобы мой пользовательский код JS работал, я просто добавил эту строку в «confing/importmap.rb».
pin_all_from "app/javascript/custom", under: "custom"
Если вы хотите использовать importmap, сделайте то, что люди уже ответили.
Но если вы добавите файл в карту импорта, это означает, что в каждом макете файл будет загружен, но если вы хотите добавить только один файл JS, я предлагаю использовать простой , с javascript_include_tag следующим образом :
<%= javascript_include_tag 'filename' %>