Rails7迁移至Importmaps+Sprockets后Stimulus/Turbo加载失败
问题
将Rails 7项目从webpacker迁移至importmaps和sprockets后,控制台出现以下错误:
Uncaught TypeError: Failed to resolve module specifier "application". Relative references must start with either "/", "./", or "../". Uncaught TypeError: Failed to resolve module specifier "@hotwired/stimulus". Relative references must start with either "/", "./", or "../".
同时Turbo仅在添加turbo_include_tags时才能生效,相关配置文件如下:
config/importmap.rb
# frozen_string_literal: true pin "application" pin "@hotwired/turbo-rails", to: "turbo.min.js" pin "@hotwired/stimulus", to: "stimulus.min.js" pin "@hotwired/stimulus-loading", to: "stimulus-loading.js" pin_all_from "app/javascript/controllers", under: "controllers" pin_all_from 'app/javascript/scripts', under: 'scripts' pin_all_from 'app/javascript/javascripts', under: 'javascripts' pin_all_from 'vendor/javascript'
layouts/application.html.erb(片段)
<head> <%= javascript_importmap_tags %> <%= turbo_include_tags %> ... </head>
app/assets/config/manifest.js
//= link application.js //= link_tree ../../javascript .js //= link_tree ../../../vendor/javascript .js //= link_tree ../images //= link_tree ../builds
app/javascript/application.js
import "@hotwired/turbo-rails" import "@hotwired/stimulus" import "./channels" import "controllers"
app/javascript/controllers/application.js
import { Application } from "@hotwired/stimulus" const application = Application.start() // Configure Stimulus development experience application.debug = false window.Stimulus = application export { application }
app/javascript/controllers/hello_controller.js
import { Controller } from "@hotwired/stimulus" export default class extends Controller { connect() { this.element.textContent = "Hello World!" } }
已确认importmap JSON中存在相关映射:
"application": "/assets/application-61a1fb89ed14a586a4ca6d042ba68b42f7e3f217eb6be4d304bf67e76401f633.js", "@hotwired/turbo-rails": "/assets/turbo.min-670aa8fec0caf84941464bb76faf6410aaabb2118b29ac6a4295df481093f051.js", "@hotwired/stimulus": "/assets/stimulus.min-9ee583d7d64bfaf202b0cf48971a673d9ed18952ae7927c50015649aebe535b6.js", "@hotwired/stimulus-loading": "/assets/stimulus-loading-d80f0feea68692981b568bbfef0ed4370b56927ae5c663421e8461a466f0618f.js",
问题排查与修复方案
1. 移除Sprockets对JavaScript文件的重复映射
你的manifest.js中通过link_tree ../../javascript .js把app/javascript下的所有JS文件都作为Sprockets资源暴露,这会和Importmap逻辑冲突。Importmap需要直接引用未被Sprockets编译的原始模块,而非带哈希的编译后文件。
修改app/assets/config/manifest.js,删除以下两行:
//= link_tree ../../javascript .js //= link_tree ../../../vendor/javascript .js
保留必要资源链接:
//= link application.js //= link_tree ../images //= link_tree ../builds
2. 移除冗余的turbo_include_tags
javascript_importmap_tags已通过Importmap加载Turbo,添加turbo_include_tags会导致重复加载,且说明原Importmap加载逻辑未生效。移除layouts/application.html.erb中的<%= turbo_include_tags %>,仅保留:
<head> <%= javascript_importmap_tags %> ... </head>
3. 确保Importmap正确加载入口模块
检查javascript_importmap_tags是否自动生成导入application模块的代码。若未生成,手动在布局中添加:
<script type="module"> import "application" </script>
也可运行bin/importmap pin application重新确认映射关系。
4. 清理缓存并重启服务器
执行以下命令清理缓存:
rails assets:clobber rails assets:precompile # 生产环境需要,开发环境可跳过
重启Rails服务器,确保配置变更生效。
错误根源说明
- 模块解析错误:Sprockets将
app/javascript下的文件编译为带哈希的资源,Importmap解析这些文件时,路径不符合ES模块的相对引用规则。 - Turbo依赖异常:直接用
turbo_include_tags绕开了Importmap,导致原Importmap配置未生效。
内容的提问来源于stack exchange,提问作者Marwann
相关产品推荐
相关产品推荐

