Rails 7 JS/CSS加载延迟及remote:true失效问题求助
问题
之前仅开发过Rails <=5版本,现在开发Rails 7应用时遇到以下资产加载异常:
- 资产应用有明显延迟:带有
remote:true的link_to,页面重载后过早点击会变成普通链接,发送HTML请求而非JS请求 - CSS加载存在可见延迟,页面先显示无样式状态0.5-1秒后才加载样式
- 图片渲染缓慢,怀疑是图片分辨率过高导致
- 对Rails 7新JS方案不熟悉,疑惑为何延迟会影响
remote:true选项
相关配置代码
importmap.rb
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" pin "jquery", to: "jquery.min.js", preload: true pin "jquery_ujs", to: "jquery_ujs.js", preload: true pin "bootstrap", to: "https://ga.jspm.io/npm:bootstrap@5.2.1/dist/js/bootstrap.esm.js" pin "@popperjs/core", to: "https://ga.jspm.io/npm:@popperjs/core@2.11.6/lib/index.js" pin "chosen-jquery", to: "chosen-jquery" pin "flatpickr", to: "flatpickr" pin_all_from "app/javascript/custom", under: "custom"
application.js
import "@hotwired/turbo-rails" import "controllers" import "jquery" import "jquery_ujs" import 'bootstrap' import 'chosen-jquery' import 'flatpickr' import "custom/choosen" import "custom/datepicker" import "custom/login_banner" import "custom/mobile_menu" import "custom/forms"
自定义JS示例(custom/forms.js)
window.form_small_img_display = function() { $("#user_avatar").change(function(){ const [file] = this.files if (file) { $(this).closest(".form-img-display-js").find("img.small-form-img-js").attr("src", URL.createObjectURL(file)) // $("img.small-form-avatar").attr("src", URL.createObjectURL(file)) } }) }; window.close_inline_form = function(){ $("close-inline-form-js > a").on("click", function(e){ e.preventDefault(); $("inline-expedition-logs-form").html(""); }) $("close-inline-update-form-js > a").on("click", function(e){ e.preventDefault(); parent = $($(this).data('id')).parent(); $($(this).data('id')).remove(); parent.prepend($(this).data('partial')) }) } $(document).on('turbo:load', window.form_small_img_display); $(document).on('turbo:load', window.close_inline_form);
manifest.js
//= link_tree ../images //= link_directory ../stylesheets .css //= link_tree ../../javascript .js //= link_tree ../../../vendor/javascript .js //= link chosen-jquery.js //= link flatpickr
解决方案
1. 修复remote:true过早点击失效问题
Rails 7默认启用Turbo,jquery_ujs与Turbo在事件处理上存在冲突,且JS加载顺序错误会导致ujs未初始化就触发链接点击:
- 调整JS加载顺序:在
application.js中将jquery_ujs移到@hotwired/turbo-rails之前导入,避免Turbo先接管事件:import "jquery" import "jquery_ujs" import "@hotwired/turbo-rails" // 移至jquery_ujs之后 import "controllers" // 其余导入保持不变 - 禁用Turbo对特定链接的接管:给
remote:true的链接添加data-turbo="false"属性,确保ujs正常拦截请求:<%= link_to "远程操作", some_path, remote: true, data: { turbo: false } %> - 确保初始化时机正确:保持自定义JS绑定在
turbo:load事件上,等待ujs完成初始化后再绑定交互逻辑。
2. 解决CSS加载延迟(FOUC问题)
- 预加载CSS:在
application.html.erb的<head>中给CSS链接添加preload属性,优先加载样式:<%= stylesheet_link_tag "application", "data-turbo-track": "reload", rel: "preload", as: "style" %> - 内联关键CSS:将首屏必需的CSS直接内联到
<head>中,避免等待外部CSS文件加载完成。 - 检查manifest配置:确认
//= link_directory ../stylesheets .css正确包含所有CSS文件,无遗漏导致额外请求。
3. 优化图片加载速度
- 压缩图片分辨率:用ImageOptim、Squoosh等工具将图片压缩至网页适配尺寸(如首屏图片宽度不超1920px),质量调至80%左右平衡画质与大小。
- 使用响应式图片:通过Rails
image_tag生成srcset和sizes属性,让浏览器按需加载合适尺寸的图片:<%= image_tag "example.jpg", srcset: { "example_480w.jpg" => "480w", "example_800w.jpg" => "800w" }, sizes: "(max-width: 600px) 480px, 800px" %> - 启用懒加载:给非首屏图片添加
loading="lazy"属性,延迟加载:<%= image_tag "lazy-image.jpg", loading: "lazy" %> - 验证资产管道配置:确保
manifest.js中//= link_tree ../images正确配置,图片已被指纹化并缓存。
4. Rails 7 JS方案适配建议
- 明确Turbo与jquery_ujs分工:Turbo是Rails 7默认JS框架,若继续使用
jquery_ujs,要么禁用Turbo对特定元素的处理,要么逐步迁移到Turbo方案(如用data-turbo-method替代remote:true,用Turbo Streams处理异步更新)。 - 本地化JS库:将jquery、jquery_ujs等常用库下载到
vendor/javascript目录,修改importmap.rb指向本地文件,避免CDN加载延迟:pin "jquery", to: "jquery.min.js", preload: true # 确保文件在vendor/javascript下 pin "jquery_ujs", to: "jquery_ujs.js", preload: true - 保持关键JS预加载:保留
importmap.rb中关键库的preload: true配置,让浏览器提前加载资源,减少初始化等待时间。
内容的提问来源于stack exchange,提问作者jakub_pietrzyk
相关产品推荐
相关产品推荐

