I'm following this question from 2020 How do I use jQuery in Rails 6.0.3.3? , but I'm not able to add jQuery to Rails 6 and Webpacker 4 in Mastodon 4.02 https://github.com/mastodon/mastodon However, I am able to add a custom.js file to load my jQuery function; it's the main jQuery library that isn't loading.
Edit 1/27/23
Takeaways:
• Why don't I have an environment.js file? Is this because of Webpacker 4?
• I tried the two other approaches below to load the jQuery library directly in app/views/layouts/application.html.haml
, but both throw the generic Mastodon error page and their are no errors using journalctl -u mastodon-web
. Neither of these work:
= javascript_pack_tag 'jquery-min'
to load app/javascript/packs/jquery-min.js
(where jquery-min.js is the jQuery library).
= javascript_include_tag "https://code.jquery.com/jquery-3.6.6.min.js"
Original question:
In Mastodon:~/live$
I run yarn add jquery
and that returns:
yarn add v1.22.19
[1/6] Validating package.json...
[2/6] Resolving packages...
[3/6] Fetching packages...
[4/6] Linking dependencies...
warning Workspaces can only be enabled in private projects.
[5/6] Building fresh packages...
[6/6] Cleaning modules...
warning Workspaces can only be enabled in private projects.
success Saved 1 new dependency.
info Direct dependencies
└─ jquery@3.6.3
info All dependencies
└─ jquery@3.6.3
Done in 24.18s.
I see that jQuery
has been added to package.json
and yarn.lock
.
I added require('jquery')
to app/javascript/packs/application.js:
import './public-path';
import loadPolyfills from '../mastodon/load_polyfills';
import { start } from '../mastodon/common';
start();
loadPolyfills().then(async () => {
const { default: main } = await import('mastodon/main');
return main();
}).catch(e => {
console.error(e);
});
require('jquery')
require('packs/custom') // custom.js file I added
But I don't have an environment.js file in the Mastodon site files, and the non-existent environment.js file should include this, as referenced in the linked question:
const { environment } = require("@rails/webpacker");
const webpack = require("webpack");
environment.plugins.append(
"Provide",
new webpack.ProvidePlugin({
$: "jquery/src/jquery",
jQuery: "jquery/src/jquery",
})
);
module.exports = environment;
I run
RAILS_ENV=production bundle exec rake tmp:cache:clear
RAILS_ENV=production bundle exec rails assets:generate_static_pages
And then
RAILS_ENV=production bundle exec rails assets:precompile
and that outputs this:
yarn install v1.22.19
[1/6] Validating package.json...
[2/6] Resolving packages...
[3/6] Fetching packages...
[4/6] Linking dependencies...
warning Workspaces can only be enabled in private projects.
[5/6] Building fresh packages...
[6/6] Cleaning modules...
Done in 18.17s.
Everything's up-to-date. Nothing to do
I exit from the root account and run
systemctl restart mastodon-*
I test for jQuery in the console and it's not loading:
But, the packs/custom.js
file is loading, as it contains
console.log("custom js is loaded");
and I see custom js is loaded
in the console.
Any ideas? Why is jQuery not loading?
Where is the environment.js file file?
Is the notice
warning Workspaces can only be enabled in private projects
a serious error?I have run
RAILS_ENV=production bundle exec rails assets:clobber
to clear Webpacker and that doesn't help with the missing jQuery library.
Edit 1/25/23:
As per mechnicov's answer, this is the shared.js file in /config/webpack/, but no luck when adding
new webpack.ProvidePlugin({ $: "jquery", jQuery: "jquery" })
const webpack = require('webpack');
const { basename, dirname, join, relative, resolve } = require('path');
const { sync } = require('glob');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const AssetsManifestPlugin = require('webpack-assets-manifest');
const extname = require('path-complete-extname');
const { env, settings, themes, output } = require('./configuration');
const rules = require('./rules');
const localePackPaths = require('./generateLocalePacks');
const extensionGlob = `**/*{${settings.extensions.join(',')}}*`;
const entryPath = join(settings.source_path, settings.source_entry_path);
const packPaths = sync(join(entryPath, extensionGlob));
module.exports = {
entry: Object.assign(
packPaths.reduce((map, entry) => {
const localMap = map;
const namespace = relative(join(entryPath), dirname(entry));
localMap[join(namespace, basename(entry, extname(entry)))] = resolve(entry);
return localMap;
}, {}),
localePackPaths.reduce((map, entry) => {
const localMap = map;
localMap[basename(entry, extname(entry, extname(entry)))] = resolve(entry);
return localMap;
}, {}),
Object.keys(themes).reduce((themePaths, name) => {
themePaths[name] = resolve(join(settings.source_path, themes[name]));
return themePaths;
}, {}),
),
output: {
filename: 'js/[name]-[chunkhash].js',
chunkFilename: 'js/[name]-[chunkhash].chunk.js',
hotUpdateChunkFilename: 'js/[id]-[hash].hot-update.js',
hashFunction: 'sha256',
path: output.path,
publicPath: output.publicPath,
},
optimization: {
runtimeChunk: {
name: 'common',
},
splitChunks: {
cacheGroups: {
default: false,
vendors: false,
common: {
name: 'common',
chunks: 'all',
minChunks: 2,
minSize: 0,
test: /^(?!.*[\\\/]node_modules[\\\/]react-intl[\\\/]).+$/,
},
},
},
occurrenceOrder: true,
},
module: {
rules: Object.keys(rules).map(key => rules[key]),
},
plugins: [
new webpack.ProvidePlugin({ $: "jquery", jQuery: "jquery" }),
new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(env))),
new webpack.NormalModuleReplacementPlugin(
/^history\//, (resource) => {
// temporary fix for https://github.com/ReactTraining/react-router/issues/5576
// to reduce bundle size
resource.request = resource.request.replace(/^history/, 'history/es');
},
),
new MiniCssExtractPlugin({
filename: 'css/[name]-[contenthash:8].css',
chunkFilename: 'css/[name]-[contenthash:8].chunk.css',
}),
new AssetsManifestPlugin({
integrity: true,
integrityHashes: ['sha256'],
entrypoints: true,
writeToDisk: true,
publicPath: true,
}),
],
resolve: {
extensions: settings.extensions,
modules: [
resolve(settings.source_path),
'node_modules',
],
},
resolveLoader: {
modules: ['node_modules'],
},
node: {
// Called by http-link-header in an API we never use, increases
// bundle size unnecessarily
Buffer: false,
},
};