如何在Rails 7引擎中配置使用importmap-rails?
问题背景
我已经在importmap-rails gem的官方仓库提交了相关问题,仍在此发布问题,希望能找到可用的临时解决方案。
初始排查情况
- 使用
rails plugin new custom_page --mountable --full命令生成的Rails 7 alpha 2或Rails 7.0版本新引擎,捆绑依赖中已经包含importmap-rails,但无法正常使用。在enginename.gemspec中添加spec.add_dependency 'importmap-rails'、在engine.rb中添加require importmap-rails均无效,bin目录下没有importmap可执行文件。
执行bundle info importmap-rails返回结果如下,说明gem已默认安装:
* importmap-rails (0.8.1) Summary: Use ESM with importmap to manage modern JavaScript in Rails without transpiling or bundling. Path: /home/jamie/.rvm/gems/ruby-3.0.0@custom_page/gems/importmap-rails-0.8.1
执行rails --tasks可看到如下任务:
rails app:importmap:install # Setup Importmap for the app
该任务是--full参数生成的测试应用自带的,并非引擎层面可用的rails命令任务,预期会出现不带app:前缀的同名任务。执行该任务会报模板错误,详情如下:
rails app:importmap:install
Don't know how to build task 'app:template' (See the list of available
tasks withrails --tasks) Did you mean? app:tmp:create
此前我在Rails 6.1.4引擎中接入webpacker完全失败,本以为importmap-rails会是更优的替代方案,因此希望得到可行的临时解决方案。
后续排查更新
在引擎目录下执行bin/importmap json会抛出如下错误:
importmap-rails-1.2.1/lib/importmap/commands.rb:63:in
json': undefined methodjoin' for nil:NilClass (NoMethodError)
require Rails.root.join("config/environment") ^^^^^ from /home/jamie/.rvm/gems/ruby-3.2.2@custom_page/gems/thor-1.2.2/lib/thor/command.rb:27:in `run' from /home/jamie/.rvm/gems/ruby-3.2.2@custom_page/gems/thor-1.2.2/lib/thor/invocation.rb:127:in `invoke_command' from /home/jamie/.rvm/gems/ruby-3.2.2@custom_page/gems/thor-1.2.2/lib/thor.rb:392:in `dispatch' from /home/jamie/.rvm/gems/ruby-3.2.2@custom_page/gems/thor-1.2.2/lib/thor/base.rb:485:in `start' from /home/jamie/.rvm/gems/ruby-3.2.2@custom_page/gems/importmap-rails-1.2.1/lib/importmap/commands.rb:147:in `<top (required)>' from <internal:/home/jamie/.rvm/rubies/ruby-3.2.2/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:37:in `require' from <internal:/home/jamie/.rvm/rubies/ruby-3.2.2/lib/ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:37:in `require' from bin/importmap:24:in `<main>'
当前相关情况说明:
- 该引擎功能目前还未接入主应用,日志中没有importmap相关报错,搜索“Importmap skipped missing path”、“skipped”和“importmap”关键词,仅早前的bug有相关报错,该bug修复后无相关记录。
- 使用标准的assets配置,有一个更新CSS文件的功能,未预编译资产,所有相关文件均为单数命名的import和import.rb。
相关配置信息
application.js初始代码:
// Configure your import map in config/importmap.rb.
资源清单配置:
//= link_directory ../stylesheets/ccs_cms/custom_page .css //= link_tree ../javascripts/ccs_cms/custom_page .js //= link_tree ../javascripts/new_ckeditor //= link ccs_cms/custom_page/jqtree.css //= link ccs_cms/custom_page/public.css
完整application.js代码:
// Configure your import map in config/importmap.rb. //= require ccs_cms/custom_page/jquery-3.6.0.min //= require ccs_cms/custom_page/jquery-ui.min //= require ccs_cms/custom_page/tree.jquery //= require ccs_cms/custom_page/sortable //= require ccs_cms/custom_page/nested_fields/addFields //= require_tree . //require("./nested-forms/addFields"); //require("./nested-forms/removeFields"); // do some javascript document.querySelector("h1").innerText = "Hi!, i'm your engine"; console.log("hi, again");
importmap.rb配置内容:
# my_engine/config/importmap.rb # NOTE: this pin works because `my_engine/app/assets/javascripts # is in the `Rails.application.config.assets.paths` pin "ccs_cms/custom_page/application"
页面head标签中生成的相关代码:
<script type="importmap" data-turbo-track="reload">{ "imports": { } }</script>
同时生成的模块引入代码:
<script type="module">import "application"</script> <script type="module">import "ccs_cms/custom_page/application"</script>
测试发现:控制台能看到“hi, again”的输出,说明console.log("hi, again");代码正常执行,但document.querySelector("h1").innerText = "Hi!, i'm your engine";没有生效。
最终解决方案
在engine.rb中添加如下代码后,所有问题都得到解决:
initializer :append_importmap_paths do |app| app.config.importmap.paths << root.join("config/importmap.rb") end
内容的提问来源于stack exchange,提问作者jamesc

