1. Quickstart - quick things you should know
2. `pin_all_from` - a few details
3. `pin` ...
4. Run in a console - when you need to figure stuff out
5. Relative imports - don't do it, unless you want to
6. Examples - to make it extra clear
如果你
没有使用
importmap-rails
,真的,你不应该有任何问题。添加一个文件,然后
import "./path/to/file"
。如果你使用
jsbundling-rails
,确保运行
bin/dev
来编译你的JavaScript。
如果你使用
importmap-rails
,就没有编译,每个文件都必须在开发和生产环境中单独提供,并且每个
import都必须映射到浏览器获取的URL。
pin
和
pin_all_from
是构建
importmap
的Rails方式。通过资产URL将导入映射到本地文件。所以请记住,
import "something"
可以映射到URL
/assets/file-123.js
,这可以映射到文件
app/some_asset_path/file.js
或者在生产环境中是
public/assets/file-123.js
。
<script type="importmap" data-turbo-track="reload">{
"imports": {
"application": "/assets/application-da9b182f12cdd2de0b86de67fc7fde8d1887a7d9ffbde46937f8cd8553cb748d.js",
"@hotwired/turbo-rails": "/assets/turbo.min-49f8a244b039107fa6d058adce740847d31bdf3832c043b860ebcda099c0688c.js",
"@hotwired/stimulus": "/assets/stimulus-a1299f07b3a1d1083084767c6e16a178a910487c81874b80623f7f2e48f99a86.js",
"@hotwired/stimulus-loading": "/assets/stimulus-loading-6024ee603e0509bba59098881b54a52936debca30ff797835b5ec6a4ef77ba37.js",
"controllers/application": "/assets/controllers/application-44e5edd38372876617b8ba873a82d48737d4c089e5180f706bdea0bb7b6370be.js",
"controllers/hello_controller": "/assets/controllers/hello_controller-29468750494634340c5c12678fe2cdc3bee371e74ac4e9de625cdb7a89faf11b.js",
"controllers": "/assets/controllers/index-e70bed6fafbd4e4aae72f8c6fce4381d19507272ff2ff0febb3f775447accb4b.js",
}
}</script>
一旦你有了一个importmap,你就需要
import
你需要的东西。Importmap并不加载任何东西,它只是一个配置。
快速入门
假设我们已经添加了一个“插件”目录:
app/
└── javascript/
├── application.js
└── plugin/
├── app.js
└── index.js
config/
└── importmap.rb
将单个文件固定在顶部:
pin "plugin/app"
pin "plugin/index"
import "plugin/app"
import "plugin/index"
或者将
插件目录及其子目录中的所有文件固定在屏幕上:
pin_all_from "app/javascript/plugin", under: "plugin"
import "plugin/app"
import "plugin"
不要使用相对导入,例如import "./plugin/app"
,在开发中可能有效,但在生产中会出现问题。
查看bin/importmap json
的输出,了解可以导入的内容,并验证importmap.rb配置。
不要在开发中预编译,它将从public/assets
提供预编译的资源,这些资源在您进行更改时不会更新。
运行bin/rails assets:clobber
以删除预编译的资源。
如果出现问题,app/javascript目录必须位于:
Rails.application.config.assets.paths
并且app/assets/config/manifest.js
中的//= link_tree ../../javascript .js
将文件固定在某个位置并不会使它们加载。它们必须在
application.js
中导入:
import "plugin"
或者,如果你想拆分你的捆绑包,你可以在你的布局中使用一个单独的模块标签:
<%= javascript_import_module_tag "plugin" %>
或模板:
<% content_for :head do %>
<%= javascript_import_module_tag "plugin" %>
<% end %>
除了
application.js
之外,您还可以添加另一个入口点,比如您添加了
app/javascript/admin.js
。您可以使用所有的引脚来导入它。
<%= javascript_importmap_tags "admin" %>
因为默认情况下,
application
的pin选项设置为
preload: true
,即使您使用
admin
覆盖了
application
的入口点,它仍会发出加载
application.js
文件的请求。预加载和导入是两个不同的概念,一个不会导致另一个。删除
preload
选项以避免不必要的请求。
pin_all_from(dir, under: nil, to: nil, preload: false)
将目录及其子目录中的所有文件都固定。
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
- 可选[1]的前缀。如果有index.js
文件,则必填。
:to
- 可选[1]的资源路径。如果:under选项被省略,则回退到back。此路径相对于Rails.application.config.assets.paths。
:preload
- 如果设置为true
,则添加一个modulepreload链接:
<link rel="modulepreload" href="/assets/turbo-5605bff731621f9ca32b71f5270be7faa9ccb0c7c810187880b97e74175d85e2.js">
注意:需要使用
:under
或
:to
中的一个。
将
插件目录中的所有文件固定住:
pin_all_from "app/javascript/plugin", under: "plugin"
{
"imports": {
"plugin/app": "/assets/plugin/app-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js",
"plugin": "/assets/plugin/index-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js"
}
}
这是它们如何相互配合的:
(如果某些东西不起作用,就采取你的选择并按照箭头的方向走,特别是
path_to_asset
部分,你可以在控制台中尝试一下,见下文)
"plugin/app": "/assets/plugin/app-04024382391bb...4145d8113cf788597.js"
:to
选项在这里可能不明显。如果更改了: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"
指定绝对路径将绕过资源管道。
pin_all_from("app/javascript/plugin", under: "plugin", to: "/plugin")
pin(name, to: nil, preload: false)
固定一个单个文件。
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
- 按钮的名称。
选项:
:to
- 可选的资源路径。如果未设置,则回退到 {name}.js
。此路径相对于 Rails.application.config.assets.paths。
:preload
- 如果设置为 true
,则添加一个 modulepreload 链接。
当固定一个本地文件时,要指定相对于
app/javascript目录(或
vendor或任何其他资源目录)的
name。
pin "plugin/app"
pin "plugin/index"
{
"imports": {
"plugin/app": "/assets/plugin/app-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js",
"plugin/index": "/assets/plugin/index-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js"
}
}
这是它们如何配合的方式:
"plugin/app": "/assets/plugin/app-04024382391bb...16cebeb14ce788597.js"
如果你想要改变针脚的名称,
:to
选项是必需的,以便给
path_to_asset一个有效的文件位置。
例如,要获得与
pin_all_from中的针脚相同的
index.js文件的针脚:
pin "plugin", to: "plugin/index"
{
"imports": {
"plugin": "/assets/plugin/index-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js"
}
}
在控制台中运行
你可以在控制台中尝试使用Importmap
,这样可以更快地调试和学习哪些功能有效,哪些功能无效:
>> helper.path_to_asset("plugin/app.js")
=> "/assets/plugin/app-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js"
>> map = Importmap::Map.new
>> map.pin_all_from("app/javascript/plugin", under: "plugin")
>> puts map.to_json(resolver: helper)
{
"imports": {
"plugin/app": "/assets/plugin/app-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js",
"plugin": "/assets/plugin/index-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js"
}
}
>> map.pin("application")
>> puts map.to_json(resolver: helper)
{
"imports": {
"application": "/assets/application-8cab2d9024ef6f21fd55792af40001fd4ee1b72b8b7e14743452fab1348b4f5a.js"
}
}
>> Rails.application.importmap
相对/绝对导入
如果你进行正确的映射,相对/绝对导入是可行的:
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
,我们使用我们的 pin 创建了一个 importmap 来实现这个。
"/assets/plugin/app": "/assets/plugin/app-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js",
这个也应该可以正常工作:
// app/javascript/plugin/index.js
import "./app"
然而,在
importmap-rails
中,虽然
import-maps
支持所有相对和绝对导入,但这似乎并不是其预期的使用情况。
示例
这应该涵盖了几乎所有内容:
.
├── app/
│ └── javascript/
│ ├── admin.js
│ ├── application.js
│ ├── extra/
│ │ └── nested/
│ │ └── directory/
│ │ └── special.js
│ └── plugin/
│ ├── app.js
│ └── index.js
└── vendor/
└── javascript/
├── downloaded.js
└── package/
└── vendored.js
从运行
bin/importmap json
的输出中得到的结果是:
pin_all_from "app/javascript"
pin_all_from "vendor/javascript"
"admin": "/assets/admin-761ee3050e9046942e5918c64dbfee795eeade86bf3fec34ec126c0d43c931b0.js",
"application": "/assets/application-d0d262731ff4f756b418662f3149e17b608d2aab7898bb983abeb669cc73bf2e.js",
"extra/nested/directory/special": "/assets/extra/nested/directory/special-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js",
"plugin/app": "/assets/plugin/app-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js",
"plugin": "/assets/plugin/index-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js",
"downloaded": "/assets/downloaded-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js",
"package/vendored": "/assets/package/vendored-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js"
请注意区别:
pin_all_from "app/javascript/extra", under: "extra"
"extra/nested/directory/special": "/assets/extra/nested/directory/special-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js"
^
pin_all_from "app/javascript/extra", to: "extra"
"nested/directory/special": "/assets/extra/nested/directory/special-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js"
^
pin_all_from "app/javascript/extra", under: "@name", to: "extra"
"@name/nested/directory/special": "/assets/extra/nested/directory/special-04024382391bb910584145d8113cf35ef376b55d125bb4516cebeb14ce788597.js"
^
请注意这个模式:
pin_all_from "app/javascript"
pin_all_from "app/javascript/extra", under: "extra"
pin_all_from "app/javascript/extra/nested", under: "extra/nested"
pin_all_from "app/javascript/extra/nested/directory", under: "extra/nested/directory"
pin_all_from "app/javascript/extra", to: "extra"
pin_all_from "app/javascript/extra/nested", to: "extra/nested"
pin_all_from "app/javascript/extra/nested/directory", to: "extra/nested/directory"
pin_all_from "app/javascript/extra", under: "@name", to: "extra"
pin_all_from "app/javascript/extra/nested", under: "@name", to: "extra/nested"
pin_all_from "app/javascript/extra/nested/directory", under: "@name", to: "extra/nested/directory"
同样的事情也适用于供应商。
pin_all_from "vendor/javascript/package", under: "package"
单个文件很容易:
pin "admin"
pin "application"
pin "extra/nested/directory/special"
pin "@extra/special", to: "extra/nested/directory/special"
pin "downloaded"
pin "renamed", to: "downloaded"
当
pin_all_from失败时:
app_js = Rails.root.join("app/javascript")
app_js.glob("**/*.js").each do |path|
name = path.relative_path_from(app_js).to_s.chomp(".js")
pin "@app/#{name}", to: name
end
import "pallete"
或import "@fractal/pallete"
起作用:pin_all_from "app/javascript/fractal_viewer", to: "fractal_viewer"
或pin_all_from "app/javascript/fractal_viewer", under: "@fractal", to: "fractal_viewer"
。但请注意,更改导入方式比调试一些边缘情况问题容易得多。在这种情况下,最好坚持使用 esbuild。 - Alexdef pin_all_relative(dir_name) ; pin_all_from "app/javascript/#{dir_name}", under: "#{Rails.application.config.assets.prefix}/#{dir_name}", to: dir_name ; end
然后每个“组件”调用一次它。解释一下:我的网站有超过200个自己的模块,分为几层深的目录,即使最深层的模块有时也会在没有引用其父目录的情况下导入进来。总共大约有600个导入语句,我需要更改而无法使用简单的查找/替换,并且我可能会失去一些灵活性和可重用性。 - cesoid