Ruby on Rails切换Webpacker后内联脚本报JQuery not defined如何解决?
问题核心原因
- Rails的webpacker默认给
javascript_pack_tag添加了defer属性,意味着webpack打包的代码会等到整个HTML DOM解析完成、所有内联JS执行完毕后才运行,你写在slim模板中的内联JS执行时,webpack暴露到全局的$还没有挂载,所以抛出未定义错误。 - application.html.slim中存在重复引入冲突:你已经在webpack中完整配置了jQuery,又额外通过
javascript_include_tag 'jquery'从sprockets引入jQuery,两处引入的jQuery变量隔离,也会导致全局变量异常。
解决方案
按顺序执行以下操作即可解决:
- 删除冗余引入:直接删掉application.html.slim中的
= javascript_include_tag 'jquery'行,避免重复加载jQuery导致的冲突。 - 修复执行顺序问题,二选一即可:
- 方案A(推荐,改造成本最低):关闭webpacker的默认defer加载,将
= javascript_pack_tag 'application'修改为:
这样webpack打包的代码会在加载完成后立刻执行,早于后续body中内联JS的运行时机,全局= javascript_pack_tag 'application', defer: false$会提前挂载完成。 - 方案B(保留defer特性):所有模板中的内联JS都包裹在
DOMContentLoaded事件监听中,等webpack代码执行完成后再运行,比如_comments.slim中的内联代码修改为:document.addEventListener('DOMContentLoaded', function() { $(function(){ var commentId = "#{ params[:comment_id] }"; if(commentId) { var $comment = $('#' + commentId); $comment.get(0).scrollIntoView(); $comment.addClass('notified'); } }); })
- 方案A(推荐,改造成本最低):关闭webpacker的默认defer加载,将
- 可选配置优化:当前environment.js中的ProvidePlugin存在重复配置,可以合并简化,避免后续维护混乱:
合并两个ProvidePlugin的配置,删除单独的jquery插件引入,修改后的environment.js对应部分如下:environment.plugins.append( "Provide", new webpack.ProvidePlugin({ $: "jquery", jQuery: "jquery", "window.jQuery": "jquery", "window.Tether": "tether", Popper: ["popper.js", "default"], }) ); // 可删除以下冗余行 // environment.plugins.prepend("jquery", jquery);
内容的提问来源于stack exchange,提问作者Antarr Byrd
相关产品推荐
相关产品推荐

