JQuery 切换到 Webpacker 后内联脚本中不存在
JQuery not present in inline scripts after switching to Webpacker
我正在将 Rails 上的 Ruby 应用程序从 sprockets 切换到 webpacker。我在现有的 slim 模板中收到内联 javascript 错误,JQuery 未定义。我尝试在 application.html.slim 中添加对 jquery 的要求,但这没有帮助。
application.html.slim
doctype html
html
head
title My Application
meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"
meta name="have-i-been-pwned-verification" value="..." /
meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"
= include_gon(watch: true)
= stylesheet_link_tag 'application', media: 'all'
= javascript_pack_tag 'application'
= javascript_include_tag 'jquery'
= csrf_meta_tags
body
= render 'layouts/navigation/main_nav', disable_search: true
= flash_messages
main.application
= yield
错误
Uncaught ReferenceError: $ is not defined
_comments.slim
.comments-wrapper.collapse.show.comments-collapse#comments
.row.comments
.col-sm-12
.row.comment-post
.col-sm-12.parent-comment-form
- if user_signed_in?
= render 'we_vote/comments/form', commentable: commentable
- unless local_assigns[:limit_comments].present?
.row.filter-row
.col-sm-12.col-lg-2.offset-md-1.offset-sm-0.text-right
.sort-label sort by
.col-lg-4.col-sm-12.mb-2
select.sort-select
option Popular
option Reply Number
option Upvote Number
option Newest
.col-lg-4.offset-lg-1.col-sm-12.offset-md-0
select.sort-select
option Today
option Last Week
option This Week
.row
.col-sm-12.comments-container class="#{'empty' unless commentable.comments.any?}"
ul.comments-list
- if local_assigns[:limit_comments]
- commentable.comments.top_level.by_popularity.limit(limit_comments).each do |comment|
= render 'we_vote/comments/comment', comment: comment, commentable: commentable, limited: true
- else
- commentable.comments.top_level.by_popularity.each do |comment|
= render 'we_vote/comments/comment', comment: comment, commentable: commentable
= render 'we_vote/comments/report_comment_modal'
javascript:
$(function(){
var commentId = "#{ params[:comment_id] }";
if(commentId) {
var $comment = $('#' + commentId);
$comment.get(0).scrollIntoView();
$comment.addClass('notified');
}
});
environment.js
const { environment } = require("@rails/webpacker");
const erb = require("./loaders/erb");
const jquery = require("./plugins/jquery");
const webpack = require("webpack");
environment.plugins.append(
"Provide",
new webpack.ProvidePlugin({
"window.Tether": "tether",
Popper: ["popper.js", "default"],
})
);
const aliasConfig = {
jquery: "jquery-ui-dist/external/jquery/jquery.js",
"jquery-ui": "jquery-ui-dist/jquery-ui.js",
};
environment.config.set("resolve.alias", aliasConfig);
environment.plugins.prepend("jquery", jquery);
environment.loaders.prepend("erb", erb);
module.exports = environment;
config/webpack/plugins/jquery.js
const webpack = require("webpack");
module.exports = new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
});
application.js
import $ from "jquery";
import autosize from "autosize";
global.$ = $;
global.jQuery = $;
import tether from "tether";
global.Tether = tether;
require("@rails/ujs").start();
require("@rails/activestorage").start();
require("channels");
require("../src/google_analytics");
require("jquery");
require("jquery-ui");
require("../src/autocomplete-rails");
require("tether");
require("popper.js/dist/umd/popper");
require("bootstrap/dist/js/bootstrap");
require("bootstrap-notify/bootstrap-notify");
require("jquery-mask-plugin");
require("select2/dist/js/select2.full.min");
require("jquery-textcomplete");
require("jquery-match-height");
require("jquery-jscroll");
require("../src/facebook");
require("../src/components/comment");
require("../src/components/discussion");
require("../src/components/follow");
require("../src/components/hashtaggable");
require("../src/components/news_feed");
require("../src/components/preview-img");
require("../src/components/question");
require("../src/components/remote_buttons");
require("../src/components/report");
require("../src/components/search");
require("../src/components/sidebar");
require("../src/components/upvote");
require("../src/components/vote");
require("../src/components/verification");
jQuery.railsAutocomplete.options.delay = 300;
jQuery.railsAutocomplete.options.autoFocus = true;
问题是您的内联脚本在 jquery 之前执行。这样做的原因是因为它内嵌在 html 中,因此可以立即使用。另一方面,jquery 不是内联的,因此浏览器必须在执行之前发出请求。
有几个选项。
选项:等待jQuery加载
一个选项是将所有内联代码包装在等待 jQuery 加载的函数中。
javascript:
document.addEventListener('DOMContentLoaded', function () {
var commentId = "#{ params[:comment_id] }";
if(commentId) {
var comment = document.getElementById(commentId);
commment.classList.add('notified');
}
}, false);
选项:存根 jQuery
另一种选择是创建存根(假)$
函数,存储对 $
的所有调用,等待 jQuery 加载并重播这些调用。 More details here
在您的 JavaScript 打包文件(例如 app/javascript/packs/application.js
)中,执行以下操作:
import jQuery from 'jquery';
global.$ = global.jQuery = jQuery;
我正在将 Rails 上的 Ruby 应用程序从 sprockets 切换到 webpacker。我在现有的 slim 模板中收到内联 javascript 错误,JQuery 未定义。我尝试在 application.html.slim 中添加对 jquery 的要求,但这没有帮助。
application.html.slim
doctype html
html
head
title My Application
meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"
meta name="have-i-been-pwned-verification" value="..." /
meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"
= include_gon(watch: true)
= stylesheet_link_tag 'application', media: 'all'
= javascript_pack_tag 'application'
= javascript_include_tag 'jquery'
= csrf_meta_tags
body
= render 'layouts/navigation/main_nav', disable_search: true
= flash_messages
main.application
= yield
错误
Uncaught ReferenceError: $ is not defined
_comments.slim
.comments-wrapper.collapse.show.comments-collapse#comments
.row.comments
.col-sm-12
.row.comment-post
.col-sm-12.parent-comment-form
- if user_signed_in?
= render 'we_vote/comments/form', commentable: commentable
- unless local_assigns[:limit_comments].present?
.row.filter-row
.col-sm-12.col-lg-2.offset-md-1.offset-sm-0.text-right
.sort-label sort by
.col-lg-4.col-sm-12.mb-2
select.sort-select
option Popular
option Reply Number
option Upvote Number
option Newest
.col-lg-4.offset-lg-1.col-sm-12.offset-md-0
select.sort-select
option Today
option Last Week
option This Week
.row
.col-sm-12.comments-container class="#{'empty' unless commentable.comments.any?}"
ul.comments-list
- if local_assigns[:limit_comments]
- commentable.comments.top_level.by_popularity.limit(limit_comments).each do |comment|
= render 'we_vote/comments/comment', comment: comment, commentable: commentable, limited: true
- else
- commentable.comments.top_level.by_popularity.each do |comment|
= render 'we_vote/comments/comment', comment: comment, commentable: commentable
= render 'we_vote/comments/report_comment_modal'
javascript:
$(function(){
var commentId = "#{ params[:comment_id] }";
if(commentId) {
var $comment = $('#' + commentId);
$comment.get(0).scrollIntoView();
$comment.addClass('notified');
}
});
environment.js
const { environment } = require("@rails/webpacker");
const erb = require("./loaders/erb");
const jquery = require("./plugins/jquery");
const webpack = require("webpack");
environment.plugins.append(
"Provide",
new webpack.ProvidePlugin({
"window.Tether": "tether",
Popper: ["popper.js", "default"],
})
);
const aliasConfig = {
jquery: "jquery-ui-dist/external/jquery/jquery.js",
"jquery-ui": "jquery-ui-dist/jquery-ui.js",
};
environment.config.set("resolve.alias", aliasConfig);
environment.plugins.prepend("jquery", jquery);
environment.loaders.prepend("erb", erb);
module.exports = environment;
config/webpack/plugins/jquery.js
const webpack = require("webpack");
module.exports = new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
});
application.js
import $ from "jquery";
import autosize from "autosize";
global.$ = $;
global.jQuery = $;
import tether from "tether";
global.Tether = tether;
require("@rails/ujs").start();
require("@rails/activestorage").start();
require("channels");
require("../src/google_analytics");
require("jquery");
require("jquery-ui");
require("../src/autocomplete-rails");
require("tether");
require("popper.js/dist/umd/popper");
require("bootstrap/dist/js/bootstrap");
require("bootstrap-notify/bootstrap-notify");
require("jquery-mask-plugin");
require("select2/dist/js/select2.full.min");
require("jquery-textcomplete");
require("jquery-match-height");
require("jquery-jscroll");
require("../src/facebook");
require("../src/components/comment");
require("../src/components/discussion");
require("../src/components/follow");
require("../src/components/hashtaggable");
require("../src/components/news_feed");
require("../src/components/preview-img");
require("../src/components/question");
require("../src/components/remote_buttons");
require("../src/components/report");
require("../src/components/search");
require("../src/components/sidebar");
require("../src/components/upvote");
require("../src/components/vote");
require("../src/components/verification");
jQuery.railsAutocomplete.options.delay = 300;
jQuery.railsAutocomplete.options.autoFocus = true;
问题是您的内联脚本在 jquery 之前执行。这样做的原因是因为它内嵌在 html 中,因此可以立即使用。另一方面,jquery 不是内联的,因此浏览器必须在执行之前发出请求。
有几个选项。
选项:等待jQuery加载
一个选项是将所有内联代码包装在等待 jQuery 加载的函数中。
javascript:
document.addEventListener('DOMContentLoaded', function () {
var commentId = "#{ params[:comment_id] }";
if(commentId) {
var comment = document.getElementById(commentId);
commment.classList.add('notified');
}
}, false);
选项:存根 jQuery
另一种选择是创建存根(假)$
函数,存储对 $
的所有调用,等待 jQuery 加载并重播这些调用。 More details here
在您的 JavaScript 打包文件(例如 app/javascript/packs/application.js
)中,执行以下操作:
import jQuery from 'jquery';
global.$ = global.jQuery = jQuery;