When we pin a file, it would go here which is a map of urls. This is the instruction for browser.
<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",
}# ^ ^
# | |
# names you use to import urls browser uses to get it
# | ^
# | |
# `------> mapped to ---------'
}</script>
Let’s say we have this directory.
app/
└── javascript/
├── application.js # <= imports go here and other js files
└── plugin/
├── app.js
└── index.js
config/
└── importmap.rb # <= pins go here
# config/importmap.rb
pin_all_from "app/javascript/plugin", under: "plugin"
# app/javascript/application.js
import "plugin/app"
import "plugin"
After “pin” we “import”. “Import” is just an action to map file to file like javascript mechanism. We don’t do relative import for javascript in rails 7. It won’t work with importmap.
= csrf_meta_tags
= csp_meta_tag
= stylesheet_link_tag "application"
= javascript_importmap_tags
In application.html, we have javascript_importmap_tags which import all preload config in importmap.
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", preload: true
pin_all_from "app/javascript/lib", under: "lib", preload: true
pin "fontawesome", to: "https://ga.jspm.io/npm:@fortawesome/fontawesome-free@6.1.1/js/all.js"
pin "jquery", to: "https://ga.jspm.io/npm:jquery@3.7.1/dist/jquery.js"
When we set preload: true, it means the files are loaded after system launched. There are three things in importmap:
- pin. Pin individual file, bookmark location of file.
- import. Map files as import in javascript.
- load. Above import doesn’t mean it can be run. Need to load it.
Loading is very important. Otherwise, your javascript won’t work. We can declare preload: true in importmap like above code. Or we import them in html.
<% content_for :head do %>
<%= javascript_import_module_tag "plugin" %>
<% end %>
# add this to the end of the <head> tag:
# <%= yield :head %>
But if it needs to be used in another preloaded file, we have to import it in this file. For example, I need to use toastr in application.js
import jquery from 'jquery'
import 'bootstrap';
import "lib/toastr.min"
It might not work because we forget to import jquery which is mandatory lib to use toastr.
In recap, we need to preload the js from importmap file config or we import js in html file (load).