Upgrade Webpack to v5

This commit is contained in:
Alex Gleason 2021-09-05 16:42:48 -05:00
parent b47685c596
commit 15283102d1
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
12 changed files with 1166 additions and 2083 deletions

View file

@ -7,6 +7,7 @@
const { trim } = require('lodash'); const { trim } = require('lodash');
const { const {
NODE_ENV,
BACKEND_URL, BACKEND_URL,
FE_SUBDIRECTORY, FE_SUBDIRECTORY,
FE_BUILD_DIR, FE_BUILD_DIR,
@ -33,6 +34,7 @@ const sanitizePath = path => {
const sanitize = obj => JSON.parse(JSON.stringify(obj)); const sanitize = obj => JSON.parse(JSON.stringify(obj));
module.exports = sanitize({ module.exports = sanitize({
NODE_ENV: NODE_ENV || 'development',
BACKEND_URL: sanitizeURL(BACKEND_URL), BACKEND_URL: sanitizeURL(BACKEND_URL),
FE_SUBDIRECTORY: sanitizeBasename(FE_SUBDIRECTORY), FE_SUBDIRECTORY: sanitizeBasename(FE_SUBDIRECTORY),
FE_BUILD_DIR: sanitizePath(FE_BUILD_DIR) || 'static', FE_BUILD_DIR: sanitizePath(FE_BUILD_DIR) || 'static',

View file

@ -88,6 +88,14 @@ export const getPointerPosition = (el, event) => {
return position; return position;
}; };
export const fileNameFromURL = str => {
const url = new URL(str);
const pathname = url.pathname;
const index = pathname.lastIndexOf('/');
return pathname.substring(index + 1);
};
const mapStateToProps = state => ({ const mapStateToProps = state => ({
displayMedia: getSettings(state).get('displayMedia'), displayMedia: getSettings(state).get('displayMedia'),
}); });

View file

@ -8,9 +8,10 @@ import './precheck';
import { default as Soapbox } from './containers/soapbox'; import { default as Soapbox } from './containers/soapbox';
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import * as OfflinePluginRuntime from '@lcdp/offline-plugin/runtime';
import * as perf from './performance';
import ready from './ready'; import ready from './ready';
import { NODE_ENV } from 'soapbox/build_config';
const perf = require('./performance');
function main() { function main() {
perf.start('main()'); perf.start('main()');
@ -19,9 +20,10 @@ function main() {
const mountNode = document.getElementById('soapbox'); const mountNode = document.getElementById('soapbox');
ReactDOM.render(<Soapbox />, mountNode); ReactDOM.render(<Soapbox />, mountNode);
if (process.env.NODE_ENV === 'production') {
if (NODE_ENV === 'production') {
// avoid offline in dev mode because it's harder to debug // avoid offline in dev mode because it's harder to debug
require('offline-plugin/runtime').install(); OfflinePluginRuntime.install();
// FIXME: Push notifications are temporarily removed // FIXME: Push notifications are temporarily removed
// store.dispatch(registerPushNotifications.register()); // store.dispatch(registerPushNotifications.register());
} }

View file

@ -1,5 +1,7 @@
'use strict'; 'use strict';
import { NODE_ENV } from 'soapbox/build_config';
// //
// Tools for performance debugging, only enabled in development mode. // Tools for performance debugging, only enabled in development mode.
// Open up Chrome Dev Tools, then Timeline, then User Timing to see output. // Open up Chrome Dev Tools, then Timeline, then User Timing to see output.
@ -8,7 +10,7 @@
let marky; let marky;
if (process.env.NODE_ENV === 'development') { if (NODE_ENV === 'development') {
if (typeof performance !== 'undefined' && performance.setResourceTimingBufferSize) { if (typeof performance !== 'undefined' && performance.setResourceTimingBufferSize) {
// Increase Firefox's performance entry limit; otherwise it's capped to 150. // Increase Firefox's performance entry limit; otherwise it's capped to 150.
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1331135 // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1331135
@ -21,13 +23,13 @@ if (process.env.NODE_ENV === 'development') {
} }
export function start(name) { export function start(name) {
if (process.env.NODE_ENV === 'development') { if (NODE_ENV === 'development') {
marky.mark(name); marky.mark(name);
} }
} }
export function stop(name) { export function stop(name) {
if (process.env.NODE_ENV === 'development') { if (NODE_ENV === 'development') {
marky.stop(name); marky.stop(name);
} }
} }

View file

@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import { NODE_ENV } from 'soapbox/build_config';
if (process.env.NODE_ENV === 'development') { if (NODE_ENV === 'development') {
const whyDidYouRender = require('@welldone-software/why-did-you-render'); const whyDidYouRender = require('@welldone-software/why-did-you-render');
whyDidYouRender(React); whyDidYouRender(React);
} }

View file

@ -49,6 +49,7 @@
"@babel/runtime": "^7.14.6", "@babel/runtime": "^7.14.6",
"@fontsource/montserrat": "^4.5.1", "@fontsource/montserrat": "^4.5.1",
"@fontsource/roboto": "^4.5.0", "@fontsource/roboto": "^4.5.0",
"@lcdp/offline-plugin": "^5.1.0",
"@popperjs/core": "^2.4.4", "@popperjs/core": "^2.4.4",
"@welldone-software/why-did-you-render": "^6.2.0", "@welldone-software/why-did-you-render": "^6.2.0",
"array-includes": "^3.0.3", "array-includes": "^3.0.3",
@ -64,8 +65,8 @@
"bowser": "^2.11.0", "bowser": "^2.11.0",
"browserslist": "^4.16.6", "browserslist": "^4.16.6",
"classnames": "^2.2.5", "classnames": "^2.2.5",
"compression-webpack-plugin": "^6.0.2", "compression-webpack-plugin": "^8.0.1",
"copy-webpack-plugin": "6.4.0", "copy-webpack-plugin": "^9.0.1",
"core-js": "^3.15.2", "core-js": "^3.15.2",
"cryptocurrency-icons": "^0.17.2", "cryptocurrency-icons": "^0.17.2",
"css-loader": "^5.2.6", "css-loader": "^5.2.6",
@ -79,8 +80,8 @@
"exif-js": "^2.3.0", "exif-js": "^2.3.0",
"file-loader": "^6.0.0", "file-loader": "^6.0.0",
"fork-awesome": "https://github.com/alexgleason/Fork-Awesome#c23fd34246a9f33c4bf24ea095a4cf26e7abe265", "fork-awesome": "https://github.com/alexgleason/Fork-Awesome#c23fd34246a9f33c4bf24ea095a4cf26e7abe265",
"html-webpack-harddisk-plugin": "^1.0.1", "html-webpack-harddisk-plugin": "^2.0.0",
"html-webpack-plugin": "^4.3.0", "html-webpack-plugin": "^5.3.2",
"http-link-header": "^1.0.2", "http-link-header": "^1.0.2",
"immutable": "^4.0.0-rc.12", "immutable": "^4.0.0-rc.12",
"imports-loader": "^1.0.0", "imports-loader": "^1.0.0",
@ -88,7 +89,7 @@
"intl": "^1.2.5", "intl": "^1.2.5",
"intl-messageformat": "^9.0.0", "intl-messageformat": "^9.0.0",
"intl-messageformat-parser": "^6.0.0", "intl-messageformat-parser": "^6.0.0",
"intl-pluralrules": "^1.1.1", "intl-pluralrules": "^1.3.0",
"is-nan": "^1.2.1", "is-nan": "^1.2.1",
"jsdoc": "~3.6.7", "jsdoc": "~3.6.7",
"lodash": "^4.7.11", "lodash": "^4.7.11",
@ -98,10 +99,11 @@
"object-assign": "^4.1.1", "object-assign": "^4.1.1",
"object-fit-images": "^3.2.3", "object-fit-images": "^3.2.3",
"object.values": "^1.1.0", "object.values": "^1.1.0",
"offline-plugin": "^5.0.7", "path-browserify": "^1.0.1",
"postcss": "^8.1.1", "postcss": "^8.1.1",
"postcss-loader": "^4.0.3", "postcss-loader": "^4.0.3",
"postcss-object-fit-images": "^1.1.2", "postcss-object-fit-images": "^1.1.2",
"process": "^0.11.10",
"prop-types": "^15.5.10", "prop-types": "^15.5.10",
"punycode": "^2.1.0", "punycode": "^2.1.0",
"qrcode.react": "^1.0.0", "qrcode.react": "^1.0.0",
@ -134,21 +136,20 @@
"sass": "^1.20.3", "sass": "^1.20.3",
"sass-loader": "^10.0.0", "sass-loader": "^10.0.0",
"semver": "^7.3.2", "semver": "^7.3.2",
"speed-measure-webpack-plugin": "^1.5.0",
"stringz": "^2.0.0", "stringz": "^2.0.0",
"substring-trie": "^1.0.2", "substring-trie": "^1.0.2",
"terser-webpack-plugin": "^4.2.3", "terser-webpack-plugin": "^5.2.3",
"tiny-queue": "^0.2.1", "tiny-queue": "^0.2.1",
"ts-jest": "^27.0.3", "ts-jest": "^27.0.3",
"twemoji": "https://github.com/twitter/twemoji#v13.0.2", "twemoji": "https://github.com/twitter/twemoji#v13.0.2",
"typescript": "^4.0.3", "typescript": "^4.0.3",
"unused-files-webpack-plugin": "^3.4.0", "util": "^0.12.4",
"uuid": "^8.0.0", "uuid": "^8.3.2",
"webpack": "^4.41.2", "webpack": "^5.52.0",
"webpack-assets-manifest": "^3.1.1", "webpack-assets-manifest": "^5.0.6",
"webpack-bundle-analyzer": "^4.0.0", "webpack-bundle-analyzer": "^4.4.2",
"webpack-cli": "^4.8.0", "webpack-cli": "^4.8.0",
"webpack-merge": "^5.2.0", "webpack-merge": "^5.8.0",
"websocket.js": "^0.1.12", "websocket.js": "^0.1.12",
"wicg-inert": "^3.1.1" "wicg-inert": "^3.1.1"
}, },
@ -172,7 +173,7 @@
"stylelint": "^13.7.2", "stylelint": "^13.7.2",
"stylelint-config-standard": "^20.0.0", "stylelint-config-standard": "^20.0.0",
"stylelint-scss": "^3.18.0", "stylelint-scss": "^3.18.0",
"webpack-dev-server": "^3.5.1", "webpack-dev-server": "^4.1.0",
"yargs": "^16.0.3" "yargs": "^16.0.3"
} }
} }

View file

@ -10,7 +10,7 @@ const settings = {
source_path: 'app', source_path: 'app',
public_root_path: FE_BUILD_DIR, public_root_path: FE_BUILD_DIR,
test_root_path: `${FE_BUILD_DIR}-test`, test_root_path: `${FE_BUILD_DIR}-test`,
cache_path: 'tmp/cache/webpacker', cache_path: 'tmp/cache',
resolved_paths: [], resolved_paths: [],
static_assets_extensions: [ '.jpg', '.jpeg', '.png', '.tiff', '.ico', '.svg', '.gif', '.eot', '.otf', '.ttf', '.woff', '.woff2', '.mp3', '.ogg', '.oga' ], static_assets_extensions: [ '.jpg', '.jpeg', '.png', '.tiff', '.ico', '.svg', '.gif', '.eot', '.otf', '.ttf', '.woff', '.woff2', '.mp3', '.ogg', '.oga' ],
extensions: [ '.mjs', '.js', '.sass', '.scss', '.css', '.module.sass', '.module.scss', '.module.css', '.png', '.svg', '.gif', '.jpeg', '.jpg' ], extensions: [ '.mjs', '.js', '.sass', '.scss', '.css', '.module.sass', '.module.scss', '.module.css', '.png', '.svg', '.gif', '.jpeg', '.jpg' ],

View file

@ -2,11 +2,8 @@
console.log('Running in development mode'); // eslint-disable-line no-console console.log('Running in development mode'); // eslint-disable-line no-console
const { merge } = require('webpack-merge'); const { merge } = require('webpack-merge');
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
const sharedConfig = require('./shared'); const sharedConfig = require('./shared');
const smp = new SpeedMeasurePlugin();
const watchOptions = {}; const watchOptions = {};
const backendUrl = process.env.BACKEND_URL || 'http://localhost:4000'; const backendUrl = process.env.BACKEND_URL || 'http://localhost:4000';
@ -51,12 +48,13 @@ if (process.env.VAGRANT) {
watchOptions.poll = 1000; watchOptions.poll = 1000;
} }
module.exports = smp.wrap(merge(sharedConfig, { module.exports = merge(sharedConfig, {
mode: 'development', mode: 'development',
cache: true, cache: true,
devtool: 'source-map', devtool: 'source-map',
stats: { stats: {
preset: 'errors-warnings',
errorDetails: true, errorDetails: true,
}, },
@ -64,32 +62,30 @@ module.exports = smp.wrap(merge(sharedConfig, {
pathinfo: true, pathinfo: true,
}, },
watchOptions: Object.assign(
{},
{ ignored: '**/node_modules/**' },
watchOptions,
),
devServer: { devServer: {
clientLogLevel: 'none',
compress: true, compress: true,
quiet: false,
disableHostCheck: true,
host: 'localhost', host: 'localhost',
port: 3036, port: 3036,
https: false, https: false,
hot: false, hot: false,
inline: true,
useLocalIp: false,
public: 'localhost:3036',
historyApiFallback: { historyApiFallback: {
disableDotRule: true, disableDotRule: true,
}, },
headers: { headers: {
'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Origin': '*',
}, },
overlay: true, client: {
stats: 'errors-warnings', overlay: true,
watchOptions: Object.assign( },
{}, static: {
{ ignored: '**/node_modules/**' }, serveIndex: true,
watchOptions, },
),
serveIndex: true,
proxy: makeProxyConfig(), proxy: makeProxyConfig(),
}, },
})); });

View file

@ -3,15 +3,12 @@ console.log('Running in production mode'); // eslint-disable-line no-console
const { merge } = require('webpack-merge'); const { merge } = require('webpack-merge');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const OfflinePlugin = require('offline-plugin'); const OfflinePlugin = require('@lcdp/offline-plugin');
const TerserPlugin = require('terser-webpack-plugin'); const TerserPlugin = require('terser-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin'); const CompressionPlugin = require('compression-webpack-plugin');
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
const sharedConfig = require('./shared'); const sharedConfig = require('./shared');
const smp = new SpeedMeasurePlugin(); module.exports = merge(sharedConfig, {
module.exports = smp.wrap(merge(sharedConfig, {
mode: 'production', mode: 'production',
devtool: 'source-map', devtool: 'source-map',
stats: 'errors-warnings', stats: 'errors-warnings',
@ -19,20 +16,21 @@ module.exports = smp.wrap(merge(sharedConfig, {
optimization: { optimization: {
minimize: true, minimize: true,
minimizer: [ minimizer: [
new TerserPlugin({ // This doesn't work unless I pass a function... wut
cache: true, compiler => {
parallel: true, new TerserPlugin({
sourceMap: true, parallel: true,
terserOptions: { terserOptions: {
warnings: false, warnings: false,
mangle: false, mangle: false,
output: { output: {
comments: false, comments: false,
},
}, },
}, }).apply(compiler);
}), },
], ],
}, },
@ -43,10 +41,11 @@ module.exports = smp.wrap(merge(sharedConfig, {
'instance', 'instance',
], ],
}), }),
new BundleAnalyzerPlugin({ // generates report.html // Generates report.html
new BundleAnalyzerPlugin({
analyzerMode: 'static', analyzerMode: 'static',
openAnalyzer: false, openAnalyzer: false,
logLevel: 'silent', // do not bother Webpacker, who runs with --json and parses stdout logLevel: 'silent',
}), }),
new OfflinePlugin({ new OfflinePlugin({
caches: { caches: {
@ -99,4 +98,4 @@ module.exports = smp.wrap(merge(sharedConfig, {
// }, // },
}), }),
], ],
})); });

View file

@ -9,9 +9,9 @@ module.exports = {
options: { options: {
name(file) { name(file) {
if (file.includes(settings.source_path)) { if (file.includes(settings.source_path)) {
return 'packs/media/[path][name]-[hash].[ext]'; return 'packs/media/[path][name]-[contenthash].[ext]';
} }
return 'packs/media/[folder]/[name]-[hash:8].[ext]'; return 'packs/media/[folder]/[name]-[contenthash:8].[ext]';
}, },
context: join(settings.source_path), context: join(settings.source_path),
}, },

View file

@ -7,25 +7,26 @@ const AssetsManifestPlugin = require('webpack-assets-manifest');
const HtmlWebpackPlugin = require('html-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackHarddiskPlugin = require('html-webpack-harddisk-plugin'); const HtmlWebpackHarddiskPlugin = require('html-webpack-harddisk-plugin');
const CopyPlugin = require('copy-webpack-plugin'); const CopyPlugin = require('copy-webpack-plugin');
const { UnusedFilesWebpackPlugin } = require('unused-files-webpack-plugin');
const { env, settings, output } = require('./configuration'); const { env, settings, output } = require('./configuration');
const rules = require('./rules'); const rules = require('./rules');
const { FE_SUBDIRECTORY } = require(join(__dirname, '..', 'app', 'soapbox', 'build_config')); const { FE_SUBDIRECTORY } = require(join(__dirname, '..', 'app', 'soapbox', 'build_config'));
const htmlWebpackPluginConfig = { const makeHtmlConfig = (params = {}) => {
template: 'app/index.ejs', return Object.assign({
chunksSortMode: 'manual', template: 'app/index.ejs',
chunks: ['common', 'locale_en', 'application', 'styles'], chunksSortMode: 'manual',
alwaysWriteToDisk: true, chunks: ['common', 'locale_en', 'application', 'styles'],
minify: { alwaysWriteToDisk: true,
collapseWhitespace: true, minify: {
removeComments: false, collapseWhitespace: true,
removeRedundantAttributes: true, removeComments: false,
removeScriptTypeAttributes: true, removeRedundantAttributes: true,
removeStyleLinkTypeAttributes: true, removeScriptTypeAttributes: true,
useShortDoctype: true, removeStyleLinkTypeAttributes: true,
}, useShortDoctype: true,
},
}, params);
}; };
module.exports = { module.exports = {
@ -37,19 +38,21 @@ module.exports = {
output: { output: {
filename: 'packs/js/[name]-[chunkhash].js', filename: 'packs/js/[name]-[chunkhash].js',
chunkFilename: 'packs/js/[name]-[chunkhash].chunk.js', chunkFilename: 'packs/js/[name]-[chunkhash].chunk.js',
hotUpdateChunkFilename: 'packs/js/[id]-[hash].hot-update.js', hotUpdateChunkFilename: 'packs/js/[id]-[contenthash].hot-update.js',
path: output.path, path: output.path,
publicPath: join(FE_SUBDIRECTORY, '/'), publicPath: join(FE_SUBDIRECTORY, '/'),
}, },
optimization: { optimization: {
chunkIds: 'total-size',
moduleIds: 'size',
runtimeChunk: { runtimeChunk: {
name: 'common', name: 'common',
}, },
splitChunks: { splitChunks: {
cacheGroups: { cacheGroups: {
default: false, default: false,
vendors: false, defaultVendors: false,
common: { common: {
name: 'common', name: 'common',
chunks: 'all', chunks: 'all',
@ -59,7 +62,6 @@ module.exports = {
}, },
}, },
}, },
occurrenceOrder: true,
}, },
module: { module: {
@ -68,6 +70,9 @@ module.exports = {
plugins: [ plugins: [
new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(env))), new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(env))),
new webpack.ProvidePlugin({
process: 'process/browser',
}),
new MiniCssExtractPlugin({ new MiniCssExtractPlugin({
filename: 'packs/css/[name]-[contenthash:8].css', filename: 'packs/css/[name]-[contenthash:8].css',
chunkFilename: 'packs/css/[name]-[contenthash:8].chunk.css', chunkFilename: 'packs/css/[name]-[contenthash:8].chunk.css',
@ -78,21 +83,9 @@ module.exports = {
writeToDisk: true, writeToDisk: true,
publicPath: true, publicPath: true,
}), }),
// https://www.npmjs.com/package/unused-files-webpack-plugin#options
new UnusedFilesWebpackPlugin({
patterns: ['app/**/*.*'],
globOptions: {
ignore: [
'node_modules/**/*',
'**/__*__/**/*',
'app/instance/about.example',
'app/soapbox/locales/whitelist_*.json',
],
},
}),
// https://github.com/jantimon/html-webpack-plugin#options // https://github.com/jantimon/html-webpack-plugin#options
new HtmlWebpackPlugin(htmlWebpackPluginConfig), new HtmlWebpackPlugin(makeHtmlConfig()),
new HtmlWebpackPlugin(Object.assign(htmlWebpackPluginConfig, { filename: '404.html' })), new HtmlWebpackPlugin(makeHtmlConfig({ filename: '404.html' })),
new HtmlWebpackHarddiskPlugin(), new HtmlWebpackHarddiskPlugin(),
new CopyPlugin({ new CopyPlugin({
patterns: [{ patterns: [{
@ -120,15 +113,13 @@ module.exports = {
resolve(settings.source_path), resolve(settings.source_path),
'node_modules', 'node_modules',
], ],
fallback: {
path: require.resolve('path-browserify'),
util: require.resolve('util'),
},
}, },
resolveLoader: { resolveLoader: {
modules: ['node_modules'], modules: ['node_modules'],
}, },
node: {
// Called by http-link-header in an API we never use, increases
// bundle size unnecessarily
Buffer: false,
},
}; };

3045
yarn.lock

File diff suppressed because it is too large Load diff