在将webpack 4.46.0升级到webpack 5.88.2和shakapacker 7.0.3(rails 6.1.7.6)后,出现了Uncaught ReferenceError: $ is not defined
错误。这里是当前的设置:
package.json
{
"name": "app",
"private": true,
"dependencies": {
"@babel/runtime": "^7.22.15",
"@fortawesome/fontawesome-free": "^6.4.2",
"@hotwired/turbo-rails": "^7.3.0",
"@popperjs/core": "^2.11.8",
"@rails/ujs": "^7.0.8",
"babel-loader": "^9.1.3",
"bootstrap": "^5.3.1",
"core-js": "^3.32.2",
"corejs-typeahead": "^1.3.3",
"css-loader": "^6.8.1",
"exports-loader": "^4.0.0",
"expose-loader": "^4.1.0",
"file-loader": "^6.2.0",
"flag-icons": "^6.11.0",
"handlebars": "^4.7.8",
"inflection": "^2.0.1",
"jbuilder": "^0.0.5",
"jquery": "^3.7.1",
"jquery-ui": "^1.13.2",
"jquery-ui-dist": "^1.13.2",
"jquery-ujs": "^1.2.3",
"jstree": "^3.3.15",
"mini-css-extract-plugin": "^2.7.6",
"moment": "^2.29.4",
"popper.js": "^1.16.1",
"postcss": "^8.4.29",
"rails-erb-loader": "^5.5.2",
"sass-loader": "^13.3.2",
"shakapacker": "^7.0.3",
"sidekiq": "^1.1.1",
"style-loader": "^3.3.3",
"webpack": "^5.88.2",
"webpack-assets-manifest": "^5.1.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1",
"webpack-merge": "^5.9.0",
"webpack-sources": "^3.2.3",
"yarn": "^1.22.19"
},
"babel": {
"presets": [
"./node_modules/shakapacker/package/babel/preset.js"
]
},
"devDependencies": {
"@babel/core": "^7.22.19",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-proposal-object-rest-spread": "^7.20.7",
"@babel/plugin-proposal-private-methods": "^7.18.6",
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-destructuring": "^7.22.15",
"@babel/plugin-transform-regenerator": "^7.22.10",
"@babel/plugin-transform-runtime": "^7.22.15",
"@babel/preset-env": "^7.22.15",
"babel-plugin-macros": "^3.1.0",
"clean-webpack-plugin": "^4.0.0",
"compression-webpack-plugin": "^10.0.0",
"moment-timezone": "^0.5.43",
"regenerator-runtime": "^0.14.0",
"sass": "^1.67.0",
"stylus": "^0.60.0",
"terser-webpack-plugin": "^5.3.9",
"url-loader": "^4.1.1"
}
}
config/webpack/webpack.config.js
const { generateWebpackConfig } = require('shakapacker')
const webpackConfig = generateWebpackConfig()
const customConfig = require('./custom')
module.exports = generateWebpackConfig()
config/webpack/custom.js
var path = require('path');
var webpack = require('webpack');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = (process.env.NODE_ENV !== "staging") && (process.env.NODE_ENV !== "production");
module.exports = {
mode: 'development',
entry: '../../app/javascript/packs/application.js',
output: {
path: path.resolve(__dirname, '../public'),
publicPath: 'public/',
filename: '[name].js', // could be omitted, that's the default
assetModuleFilename: 'public/images/[name].[ext]'
},
resolve: {
modules: ['node_modules'],
extensions: ['.css', '.sass', '.scss', '.js', '.json'],
alias: {
jquery: 'jquery',
'jquery-ui': 'jquery-ui/jquery-ui.js',
typeahead: 'core-typeahead',
}
},
module: {
rules: [
{
test: /\.html\.erb$/,
loader: 'rails-erb-loader'
},
{
test: require.resolve('jquery'),
loader: 'expose-loader',
options: {
exposes: ['$', 'jQuery'],
},
},
{
test: /\.s[ac]ss$/i,
use: [
devMode ? "style-loader" : MiniCssExtractPlugin.loader,
"css-loader",
"postcss-loader",
"sass-loader",
"style-loader",
],
},
{
test: /\.(jpe?g|png|gif|svg|gif|png|jpg|eot|ttf|otf|woff|woff2)$/i,
loader: 'file-loader'
},
]
},
performance: {
hints: false,
maxEntrypointSize: 512000,
maxAssetSize: 512000
},
optimization: {
splitChunks: {
chunks: 'all'
}
},
progress: true,
stats: {
errorDetails: true, //this does show errors
colors: true,
modules: true,
reasons: true
}
}
config/webpack/environment.js
const webpack = require('webpack');
const { generateWebpackConfig } = require('shakapacker')
const erb = require('./loaders/erb');
const customConfig = {
resolve: {
fallback: {
dgram: false,
fs: false,
net: false,
tls: false,
child_process: false
}
}
};
environment.plugins.prepend('Provide',
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
jquery: 'jquery',
Popper: ['popper.js', 'default'],
Rails: ['@rails/ujs'],
moment: 'moment'
})
);
environment.loaders.prepend('erb', erb);
environment.config.merge(customConfig);
module.exports = environment;
config/webpack/development.js
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
const environment = require('./environment')
module.exports = environment.toWebpackConfig()
app/assets/JavaScript/packs/application.js
...
import $ from 'jquery';
window.jQuery = $;
window.$ = $;
import 'jquery-ui-dist/jquery-ui';
...
app/views/layouts/application.html.erb
...
<%= stylesheet_pack_tag 'application', :media => "all", :data => {:turbo => {:track => 'reload'}} %>
<%= javascript_pack_tag 'application', :data => {:turbo => {:track => 'reload'}, :defer => false} %>
...
没有出现编译错误,有没有什么线索可以解释为什么jquery没有加载?
2条答案
按热度按时间trnvg8h31#
请查看Shakapacker README file和v6 upgrade docs,其中提出了两种方法。我在这里引用它们:
1.使用
expose-loader
如果你使用
expose-loader
全局公开jquery,在app/javascript/application.js
中使用import $ from "expose-loader?exposes=$,jQuery!jquery"
,将defer: false
选项传递给javascript_pack_tag
。1.在webpack配置中使用
resolve.alias
:1.在webpack配置中使用ProvidePlugin
neskvpey2#
我发现这个错误与webpacker/shakapacker配置无关,而是由于缺少'defer'属性而没有正确加载的
js.erb
文件。app/views/layouts/application.html.erb
Webpacker helper
javascript_pack_tag
将生成HTML代码,并将defer
设置为默认值true
(这是webpacker 5中的新功能)。因此,
js.erb
文件不会等待脚本,它将在jquery之前加载。将defer = true
添加到javascript_include_tag
修复了此问题