Bootstrap模态框与折叠面板本地正常,Heroku部署后失效求助
Heroku部署后Bootstrap模态框/折叠面板失效排查思路
核心错误提示:Uncaught TypeError: Failed to resolve module specifier "@hotwired/turbo-rails". Relative references must start with either "/", "./", or "../"
该错误会阻断JavaScript执行流程,导致Bootstrap依赖的交互逻辑无法初始化,这是模态框和折叠面板失效的直接原因。以下是具体排查步骤:
1. 校验Turbo Rails的生产环境配置
- 确认Gemfile中存在
gem "turbo-rails",且Heroku部署时完成了bundle install(可通过heroku logs查看部署日志验证)。 - 检查JS入口文件(如
app/javascript/application.js)的引入语法:必须是import "@hotwired/turbo-rails",确保webpacker/jsbundling-rails在生产环境正确打包该模块。 - 若使用Importmap,确认
config/importmap.rb中添加了pin "@hotwired/turbo-rails",且生产环境已完成importmap编译。
2. 修复Bootstrap与Turbo的兼容性问题
Turbo的页面动态替换机制会导致Bootstrap组件仅在首次页面加载时初始化,后续动态加载的内容无法触发交互。需在Turbo事件中重新初始化组件:
document.addEventListener('turbo:load', function() { // 初始化所有模态框 document.querySelectorAll('.modal').forEach(modal => new bootstrap.Modal(modal)); // 初始化所有折叠面板 document.querySelectorAll('.accordion-button').forEach(btn => new bootstrap.Collapse(btn)); });
3. 检查生产环境JS打包流程
- 若使用webpacker:确认
config/webpack/production.js配置无遗漏,Turbo模块已被纳入打包范围。 - 若使用jsbundling-rails(esbuild/rollup等):检查
package.json中是否安装@hotwired/turbo-rails依赖,且Heroku部署时正确执行了JS build命令(查看部署日志中的build步骤输出)。 - 验证Heroku静态资源:确认
public/assets目录下存在包含Turbo代码的编译后JS文件。
4. 确认依赖版本兼容性
- 核对
Gemfile.lock和package-lock.json(或yarn.lock)中的版本,确保生产环境安装的turbo-rails、bootstrap及JS工具版本与本地开发环境一致,避免版本冲突导致的模块加载失败。
5. 排查Heroku部署日志细节
通过heroku logs --tail查看完整部署日志,重点关注:
- bundle install阶段是否有依赖安装失败提示
- JS打包过程是否出现报错
- 静态资源编译是否完成
代码示例
模态框代码(修正语法错误):
<button class="btn btn-black-outline" data-bs-toggle="modal" data-bs-target="#newProductModal"> Add a New Product </button> <div class="modal fade" id="newProductModal" tabindex="-1" aria-labelledby="newProductModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="newProductModalLabel">Add a New Product</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <%= render partial: "products/modal_innards", locals: { product: product } %> </div> </div> </div>
折叠面板代码:
<div class="accordion mb-5" id="accordionKits"> <div class="accordion-item"> <h3 class="accordion-header" id="headingOne1"> <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne1" aria-expanded="false" aria-controls="collapseOne1"> What shrouds (radiator plastic) does the Aloop kit use? </button> </h3> <div class="accordion-collapse collapse" id="collapseOne1" aria-labelledby="headingOne1" data-bs-parent="#accordionKits"> <div class="accordion-body"> The Aloop 4SMX seat/tank kit uses shrouds from the 1999 CR250 Honda. Currently we are supplying Acerbis brand shrouds with our kits, but you could also use genuine Honda shrouds, or even UFO or some other brand. Any shrouds meant to fit the 1999 CR250 should fit our kit. We do modify the shrouds slightly to fit our tank though. Basically the mods consist of cutting off the rear shroud bolt hole and mount, and removing the vertical reinforcing rib on the inside of the shroud. If you're fitting your own replacement shrouds use your original Aloop shroud as a guide. </div> </div> </div> .... (more items) .... </div>
内容的提问来源于stack exchange,提问作者Liz
相关产品推荐
相关产品推荐

