Skip to content

Make importmap paths configurable #62

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ There's [native support for import maps in Chrome/Edge 89+](https://caniuse.com/

## Installation

Importmap for Rails is automatically included in Rails 7+ for new applications, but you can also install it manually in existing applications:
Importmap for Rails is automatically included in Rails 7+ for new applications, but you can also install it manually in existing applications:

1. Add `importmap-rails` to your Gemfile with `gem 'importmap-rails'`
2. Run `./bin/bundle install`
Expand Down Expand Up @@ -188,7 +188,7 @@ pin "@github/hotkey", to: "https://ga.jspm.io/npm:@github/hotkey@1.4.4/dist/inde
pin "md5", to: "https://cdn.jsdelivr.net/npm/md5@2.3.0/md5.js"

# app/views/layouts/application.html.erb
<%= javascript_importmap_tags %>
<%= javascript_importmap_tags %>

# will include the following link before the importmap is setup:
<link rel="modulepreload" href="https://ga.jspm.io/npm:@github/hotkey@1.4.4/dist/index.js">
Expand All @@ -199,16 +199,17 @@ pin "md5", to: "https://cdn.jsdelivr.net/npm/md5@2.3.0/md5.js"

By default, Rails loads import map definition from the application's `config/importmap.rb` to the `Importmap::Map` object available at `Rails.application.importmap`.

You can combine multiple import maps by drawing their definitions onto the `Rails.application.importmap`. For example, appending import maps defined in Rails engines:
You can combine multiple import maps by adding paths to additional import map configs to `Rails.application.config.importmap.paths`. For example, appending import maps defined in Rails engines:

```ruby
# my_engine/lib/my_engine/engine.rb

module MyEngine
class Engine < ::Rails::Engine
# ...
initializer "my-engine.importmap", after: "importmap" do |app|
app.importmap.draw(Engine.root.join("config/importmap.rb"))
initializer "my-engine.importmap", before: "importmap" do |app|
app.config.importmap.paths << Engine.root.join("config/importmap.rb")
# ...
end
end
end
Expand Down Expand Up @@ -238,14 +239,19 @@ end

Generating the import map json and modulepreloads may require resolving hundreds of assets. This can take a while, so these operations are cached, but in development and test, we watch for changes to both `config/importmap.rb` and files in `app/javascript` to clear this cache. This feature can be controlled in an environment configuration file via the boolean `config.importmap.sweep_cache`.

If you're pinning local files from outside of `app/javascript`, you'll need to add them to the cache sweeper configuration or restart your development server upon changes to those external files. To add them to the configuration to clear the cache on changes, for instance when locally developing an engine, use an initializer like the following sample `config/initializers/importmap-caching.rb`:
If you're pinning local files from outside of `app/javascript`, you'll need to add them to the cache sweeper configuration or restart your development server upon changes to those external files. For example, here's how you can do it for Rails engine:

```ruby
if Rails.env.development?
Rails.application.importmap.cache_sweeper watches: [
Rails.application.root.join("app/javascript"),
MyEngine::Engine.root.join("app/assets/javascripts"),
]
# my_engine/lib/my_engine/engine.rb

module MyEngine
class Engine < ::Rails::Engine
# ...
initializer "my-engine.importmap", before: "importmap" do |app|
# ...
app.config.importmap.cache_sweepers << Engine.root.join("app/assets/javascripts")
end
end
end
```

Expand Down
14 changes: 8 additions & 6 deletions lib/importmap/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,20 @@
module Importmap
class Engine < ::Rails::Engine
config.importmap = ActiveSupport::OrderedOptions.new
config.importmap.paths = []
config.importmap.sweep_cache = Rails.env.development? || Rails.env.test?
config.importmap.cache_sweepers = []
config.importmap.rescuable_asset_errors = []

config.autoload_once_paths = %W( #{root}/app/helpers )

initializer "importmap" do |app|
app.importmap = Importmap::Map.new.draw("config/importmap.rb")
app.importmap = Importmap::Map.new
app.config.importmap.paths << app.root.join("config/importmap.rb")
app.config.importmap.paths.each { |path| app.importmap.draw(path) }
end

initializer "importmap.reloader" do |app|
app.config.paths.add "config/importmap.rb"

Importmap::Reloader.new.tap do |reloader|
reloader.execute
app.reloaders << reloader
Expand All @@ -27,9 +29,9 @@ class Engine < ::Rails::Engine

initializer "importmap.cache_sweeper" do |app|
if app.config.importmap.sweep_cache
app.importmap.cache_sweeper watches: [
app.root.join("app/javascript"), app.root.join("vendor/javascript")
]
app.config.importmap.cache_sweepers << app.root.join("app/javascript")
app.config.importmap.cache_sweepers << app.root.join("vendor/javascript")
app.importmap.cache_sweeper(watches: app.config.importmap.cache_sweepers)

ActiveSupport.on_load(:action_controller_base) do
before_action { Rails.application.importmap.cache_sweeper.execute_if_updated }
Expand Down
2 changes: 1 addition & 1 deletion lib/importmap/reloader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def updater
end

def import_map_paths
config.paths["config/importmap.rb"].existent
config.importmap.paths
end

def config
Expand Down