mirror of https://github.com/zulip/zulip.git
webpack: Upgrade to Webpack 5.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
parent
c460351898
commit
79b88b79bb
32
package.json
32
package.json
|
@ -22,12 +22,11 @@
|
|||
"babel-loader": "^8.0.6",
|
||||
"babel-plugin-formatjs": "^10.2.6",
|
||||
"blueimp-md5": "^2.10.0",
|
||||
"cache-loader": "^4.0.0",
|
||||
"clean-css": "^5.1.0",
|
||||
"clipboard": "^2.0.4",
|
||||
"core-js": "^3.6.5",
|
||||
"css-loader": "^5.0.0",
|
||||
"css-minimizer-webpack-plugin": "^1.3.0",
|
||||
"css-loader": "^6.2.0",
|
||||
"css-minimizer-webpack-plugin": "^3.0.2",
|
||||
"css.escape": "^1.5.1",
|
||||
"date-fns": "^2.16.1",
|
||||
"date-fns-tz": "^1.1.1",
|
||||
|
@ -36,27 +35,26 @@
|
|||
"emoji-datasource-twitter": "^7.0.2",
|
||||
"error-stack-parser": "^2.0.2",
|
||||
"eslint-plugin-formatjs": "^2.16.0",
|
||||
"expose-loader": "^1.0.0",
|
||||
"file-loader": "^6.0.0",
|
||||
"expose-loader": "^3.0.0",
|
||||
"flatpickr": "^4.5.7",
|
||||
"font-awesome": "^4.7.0",
|
||||
"font-subset-loader2": "^1.1.7",
|
||||
"ga-gtag": "^1.0.1",
|
||||
"handlebars": "^4.7.2",
|
||||
"handlebars-loader": "^1.7.1",
|
||||
"html-webpack-plugin": "^4.0.0-beta.8",
|
||||
"html-webpack-plugin": "^5.3.2",
|
||||
"jquery": "^3.4.1",
|
||||
"jquery-caret-plugin": "^1.5.2",
|
||||
"jquery-validation": "^1.19.0",
|
||||
"katex": "^0.13.2",
|
||||
"lodash": "^4.17.19",
|
||||
"mini-css-extract-plugin": "^1.2.0",
|
||||
"mini-css-extract-plugin": "^2.2.2",
|
||||
"plotly.js": "^2.0.0",
|
||||
"postcss": "^8.0.3",
|
||||
"postcss-calc": "^8.0.0",
|
||||
"postcss-extend-rule": "^3.0.0",
|
||||
"postcss-import": "^14.0.2",
|
||||
"postcss-loader": "^4.0.2",
|
||||
"postcss-loader": "^6.1.1",
|
||||
"postcss-media-minmax": "https://github.com/andersk/postcss-media-minmax.git#01239f17f4a9872ace1dd133cee526a7de4ac9f5",
|
||||
"postcss-nested": "^5.0.0",
|
||||
"postcss-prefixwrap": "^1.24.0",
|
||||
|
@ -70,14 +68,13 @@
|
|||
"source-sans": "^3.28.0",
|
||||
"spectrum-colorpicker": "^1.8.1",
|
||||
"stacktrace-gps": "^3.0.4",
|
||||
"style-loader": "^2.0.0",
|
||||
"terser-webpack-plugin": "^4.1.0",
|
||||
"style-loader": "^3.2.1",
|
||||
"text-field-edit": "^3.1.0",
|
||||
"tippy.js": "^6.2.7",
|
||||
"turndown": "^7.0.0",
|
||||
"url-loader": "^4.1.1",
|
||||
"webfonts-loader": "^7.0.1",
|
||||
"webpack": "^4.33.0",
|
||||
"webpack": "^5.52.1",
|
||||
"webpack-bundle-tracker": "^1.2.0",
|
||||
"webpack-cli": "^4.6.0",
|
||||
"winchan": "^0.2.1",
|
||||
|
@ -87,14 +84,12 @@
|
|||
"@babel/eslint-parser": "^7.11.3",
|
||||
"@formatjs/cli": "^4.2.6",
|
||||
"@types/clean-css": "^4.2.2",
|
||||
"@types/css-minimizer-webpack-plugin": "~1.1.3",
|
||||
"@types/css-minimizer-webpack-plugin": "^3.0.2",
|
||||
"@types/jquery": "^3.3.31",
|
||||
"@types/lodash": "^4.14.172",
|
||||
"@types/mini-css-extract-plugin": "1.4.0",
|
||||
"@types/mini-css-extract-plugin": "^2.2.0",
|
||||
"@types/node": "^14.0.11",
|
||||
"@types/node-fetch": "^2.5.8",
|
||||
"@types/terser-webpack-plugin": "^4.1.0",
|
||||
"@types/webpack": "^4.41.31",
|
||||
"@types/webpack-dev-server": "^4.1.0",
|
||||
"@types/zxcvbn": "^4.4.1",
|
||||
"@typescript-eslint/eslint-plugin": "^4.0.1",
|
||||
|
@ -103,6 +98,7 @@
|
|||
"callsites": "^3.1.0",
|
||||
"diff": "^5.0.0",
|
||||
"difflib": "^0.2.4",
|
||||
"enhanced-resolve": "^5.8.2",
|
||||
"es-check": "^6.0.0",
|
||||
"eslint": "^7.2.0",
|
||||
"eslint-config-prettier": "^8.0.0",
|
||||
|
@ -135,12 +131,6 @@
|
|||
"resolutions": {
|
||||
"/source-map": "https://codeload.github.com/benthemonkey/source-map/tar.gz/d95423f77edef6cbb9e21d2d6014c7de85ae220a"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "rm -rf ./var/webpack-cache",
|
||||
"lint": "eslint --quiet --cache",
|
||||
"lint-fix": "eslint --quiet --fix",
|
||||
"lint-loud": "eslint static/js frontend_tests --cache"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/zulip/zulip.git"
|
||||
|
|
|
@ -4,94 +4,111 @@
|
|||
|
||||
import path from "path";
|
||||
|
||||
import type webpack from "webpack";
|
||||
import {Template} from "webpack";
|
||||
import type {ResolveRequest} from "enhanced-resolve";
|
||||
import type {Chunk, Compiler, WebpackPluginInstance} from "webpack";
|
||||
import {NormalModule, Template} from "webpack";
|
||||
|
||||
export default class DebugRequirePlugin {
|
||||
apply(compiler: webpack.Compiler): void {
|
||||
const resolved = new Map();
|
||||
export default class DebugRequirePlugin implements WebpackPluginInstance {
|
||||
apply(compiler: Compiler): void {
|
||||
const resolved = new Map<string, Set<string>>();
|
||||
const nameSymbol = Symbol("DebugRequirePluginName");
|
||||
let debugRequirePath: string | undefined;
|
||||
type NamedRequest = ResolveRequest & {
|
||||
[nameSymbol]?: string;
|
||||
};
|
||||
let debugRequirePath: string | false = false;
|
||||
|
||||
(compiler as any).resolverFactory.hooks.resolver
|
||||
compiler.resolverFactory.hooks.resolver
|
||||
.for("normal")
|
||||
.tap("DebugRequirePlugin", (resolver: any) => {
|
||||
resolver.getHook("beforeRawModule").tap("DebugRequirePlugin", (req: any) => {
|
||||
req[nameSymbol] = req[nameSymbol] || req.request;
|
||||
});
|
||||
|
||||
resolver.getHook("beforeRelative").tap("DebugRequirePlugin", (req: any) => {
|
||||
const inPath = path.relative(compiler.context, req.path);
|
||||
if (!inPath.startsWith("../")) {
|
||||
req[nameSymbol] = req[nameSymbol] || "./" + inPath;
|
||||
.tap("DebugRequirePlugin", (resolver) => {
|
||||
resolver.getHook("beforeRawModule").tap("DebugRequirePlugin", (req) => {
|
||||
if (!(nameSymbol in req)) {
|
||||
(req as NamedRequest)[nameSymbol] = req.request;
|
||||
}
|
||||
return undefined!;
|
||||
});
|
||||
|
||||
resolver.getHook("beforeResolved").tap("DebugRequirePlugin", (req: any) => {
|
||||
if (req[nameSymbol]) {
|
||||
const names = resolved.get(req.path);
|
||||
if (names) {
|
||||
names.add(req[nameSymbol]);
|
||||
} else {
|
||||
resolved.set(req.path, new Set([req[nameSymbol]]));
|
||||
resolver.getHook("beforeRelative").tap("DebugRequirePlugin", (req) => {
|
||||
if (req.path !== false) {
|
||||
const inPath = path.relative(compiler.context, req.path);
|
||||
if (!inPath.startsWith("../") && !(nameSymbol in req)) {
|
||||
(req as NamedRequest)[nameSymbol] = "./" + inPath;
|
||||
}
|
||||
}
|
||||
return undefined!;
|
||||
});
|
||||
|
||||
resolver
|
||||
.getHook("beforeResolved")
|
||||
.tap("DebugRequirePlugin", (req: ResolveRequest) => {
|
||||
const name = (req as NamedRequest)[nameSymbol];
|
||||
if (name !== undefined && req.path !== false) {
|
||||
const names = resolved.get(req.path);
|
||||
if (names) {
|
||||
names.add(name);
|
||||
} else {
|
||||
resolved.set(req.path, new Set([name]));
|
||||
}
|
||||
}
|
||||
return undefined!;
|
||||
});
|
||||
});
|
||||
|
||||
compiler.hooks.beforeCompile.tapPromise(
|
||||
"DebugRequirePlugin",
|
||||
async ({normalModuleFactory}: any) => {
|
||||
async ({normalModuleFactory}) => {
|
||||
const resolver = normalModuleFactory.getResolver("normal");
|
||||
debugRequirePath = await new Promise((resolve, reject) =>
|
||||
debugRequirePath = await new Promise((resolve) =>
|
||||
resolver.resolve(
|
||||
{},
|
||||
__dirname,
|
||||
"./debug-require",
|
||||
{},
|
||||
(err?: Error, result?: string) => (err ? reject(err) : resolve(result)),
|
||||
(err?: Error | null, result?: string | false) =>
|
||||
resolve(err ? false : result!),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
compiler.hooks.compilation.tap("DebugRequirePlugin", (compilation: any) => {
|
||||
compilation.mainTemplate.hooks.beforeStartup.tap(
|
||||
compiler.hooks.compilation.tap("DebugRequirePlugin", (compilation) => {
|
||||
compilation.mainTemplate.hooks.bootstrap.tap(
|
||||
"DebugRequirePlugin",
|
||||
(source: string, chunk: webpack.compilation.Chunk) => {
|
||||
(source: string, chunk: Chunk) => {
|
||||
const ids: [string, string | number][] = [];
|
||||
let debugRequireId;
|
||||
chunk.hasModuleInGraph(
|
||||
({resource, rawRequest, id}: any) => {
|
||||
if (resource === debugRequirePath) {
|
||||
debugRequireId = id;
|
||||
}
|
||||
for (const name of resolved.get(resource) || []) {
|
||||
ids.push([
|
||||
rawRequest.slice(0, rawRequest.lastIndexOf("!") + 1) + name,
|
||||
id,
|
||||
]);
|
||||
let hasDebugRequire = false;
|
||||
compilation.chunkGraph.hasModuleInGraph(
|
||||
chunk,
|
||||
(m) => {
|
||||
if (m instanceof NormalModule) {
|
||||
const id = compilation.chunkGraph.getModuleId(m);
|
||||
if (m.resource === debugRequirePath) {
|
||||
hasDebugRequire = true;
|
||||
}
|
||||
for (const name of resolved.get(m.resource) ?? []) {
|
||||
ids.push([
|
||||
m.rawRequest.slice(0, m.rawRequest.lastIndexOf("!") + 1) +
|
||||
name,
|
||||
id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
() => true,
|
||||
);
|
||||
|
||||
if (debugRequireId === undefined) {
|
||||
if (!hasDebugRequire) {
|
||||
return source;
|
||||
}
|
||||
|
||||
ids.sort();
|
||||
const {requireFn} = compilation.mainTemplate;
|
||||
return Template.asString([
|
||||
source,
|
||||
`${requireFn}(${JSON.stringify(
|
||||
debugRequireId,
|
||||
)}).initialize(${JSON.stringify(
|
||||
`__webpack_require__.debugRequireIds = ${JSON.stringify(
|
||||
Object.fromEntries(ids),
|
||||
null,
|
||||
"\t",
|
||||
)}, modules);`,
|
||||
)};`,
|
||||
]);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -2,22 +2,18 @@
|
|||
|
||||
/* global __webpack_require__ */
|
||||
|
||||
var webpackModules;
|
||||
|
||||
function debugRequire(request) {
|
||||
if (!Object.prototype.hasOwnProperty.call(debugRequire.ids, request)) {
|
||||
throw new Error("Cannot find module '" + request + "'");
|
||||
}
|
||||
var moduleId = debugRequire.ids[request];
|
||||
if (!Object.prototype.hasOwnProperty.call(webpackModules, moduleId)) {
|
||||
if (!Object.prototype.hasOwnProperty.call(__webpack_require__.m, moduleId)) {
|
||||
throw new Error("Module '" + request + "' has not been loaded yet");
|
||||
}
|
||||
return __webpack_require__(moduleId);
|
||||
}
|
||||
|
||||
debugRequire.initialize = function (ids, modules) {
|
||||
debugRequire.ids = ids;
|
||||
webpackModules = modules;
|
||||
};
|
||||
debugRequire.r = __webpack_require__;
|
||||
debugRequire.ids = __webpack_require__.debugRequireIds;
|
||||
|
||||
module.exports = debugRequire;
|
||||
|
|
|
@ -48,4 +48,4 @@ API_FEATURE_LEVEL = 97
|
|||
# historical commits sharing the same major version, in which case a
|
||||
# minor version bump suffices.
|
||||
|
||||
PROVISION_VERSION = "159.2"
|
||||
PROVISION_VERSION = "160.0"
|
||||
|
|
|
@ -5,7 +5,6 @@ import path from "path";
|
|||
import CssMinimizerPlugin from "css-minimizer-webpack-plugin";
|
||||
import HtmlWebpackPlugin from "html-webpack-plugin";
|
||||
import MiniCssExtractPlugin from "mini-css-extract-plugin";
|
||||
import TerserPlugin from "terser-webpack-plugin";
|
||||
import webpack from "webpack";
|
||||
import BundleTracker from "webpack-bundle-tracker";
|
||||
|
||||
|
@ -13,20 +12,26 @@ import DebugRequirePlugin from "./tools/debug-require-webpack-plugin";
|
|||
import assets from "./tools/webpack.assets.json";
|
||||
import dev_assets from "./tools/webpack.dev-assets.json";
|
||||
|
||||
const cacheLoader: webpack.RuleSetUseItem = {
|
||||
loader: "cache-loader",
|
||||
options: {
|
||||
cacheDirectory: path.resolve(__dirname, "var/webpack-cache"),
|
||||
},
|
||||
};
|
||||
|
||||
export default (env: {minimize?: boolean} = {}, argv: {mode?: string}): webpack.Configuration[] => {
|
||||
const production: boolean = argv.mode === "production";
|
||||
|
||||
const config: webpack.Configuration = {
|
||||
name: "frontend",
|
||||
const baseConfig: webpack.Configuration = {
|
||||
mode: production ? "production" : "development",
|
||||
context: __dirname,
|
||||
cache: {
|
||||
type: "filesystem",
|
||||
buildDependencies: {
|
||||
config: [__filename],
|
||||
},
|
||||
},
|
||||
snapshot: {
|
||||
immutablePaths: ["/srv/zulip-npm-cache"],
|
||||
},
|
||||
};
|
||||
|
||||
const frontendConfig: webpack.Configuration = {
|
||||
...baseConfig,
|
||||
name: "frontend",
|
||||
entry: production
|
||||
? assets
|
||||
: Object.fromEntries(
|
||||
|
@ -81,7 +86,7 @@ export default (env: {minimize?: boolean} = {}, argv: {mode?: string}): webpack.
|
|||
path.resolve(__dirname, "static/shared/js"),
|
||||
path.resolve(__dirname, "static/js"),
|
||||
],
|
||||
use: [cacheLoader, "babel-loader"],
|
||||
loader: "babel-loader",
|
||||
},
|
||||
// regular css files
|
||||
{
|
||||
|
@ -89,7 +94,6 @@ export default (env: {minimize?: boolean} = {}, argv: {mode?: string}): webpack.
|
|||
exclude: path.resolve(__dirname, "static/styles"),
|
||||
use: [
|
||||
MiniCssExtractPlugin.loader,
|
||||
cacheLoader,
|
||||
{
|
||||
loader: "css-loader",
|
||||
options: {
|
||||
|
@ -104,7 +108,6 @@ export default (env: {minimize?: boolean} = {}, argv: {mode?: string}): webpack.
|
|||
include: path.resolve(__dirname, "static/styles"),
|
||||
use: [
|
||||
MiniCssExtractPlugin.loader,
|
||||
cacheLoader,
|
||||
{
|
||||
loader: "css-loader",
|
||||
options: {
|
||||
|
@ -122,54 +125,48 @@ export default (env: {minimize?: boolean} = {}, argv: {mode?: string}): webpack.
|
|||
},
|
||||
{
|
||||
test: /\.hbs$/,
|
||||
use: [
|
||||
cacheLoader,
|
||||
{
|
||||
loader: "handlebars-loader",
|
||||
options: {
|
||||
ignoreHelpers: true,
|
||||
// Tell webpack not to explicitly require these.
|
||||
knownHelpers: [
|
||||
"if",
|
||||
"unless",
|
||||
"each",
|
||||
"with",
|
||||
// The ones below are defined in static/js/templates.js
|
||||
"plural",
|
||||
"eq",
|
||||
"and",
|
||||
"or",
|
||||
"not",
|
||||
"t",
|
||||
"tr",
|
||||
"rendered_markdown",
|
||||
],
|
||||
preventIndent: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
loader: "handlebars-loader",
|
||||
options: {
|
||||
ignoreHelpers: true,
|
||||
// Tell webpack not to explicitly require these.
|
||||
knownHelpers: [
|
||||
"if",
|
||||
"unless",
|
||||
"each",
|
||||
"with",
|
||||
// The ones below are defined in static/js/templates.js
|
||||
"plural",
|
||||
"eq",
|
||||
"and",
|
||||
"or",
|
||||
"not",
|
||||
"t",
|
||||
"tr",
|
||||
"rendered_markdown",
|
||||
],
|
||||
preventIndent: true,
|
||||
},
|
||||
},
|
||||
// load fonts and files
|
||||
{
|
||||
test: /\.(eot|jpg|svg|ttf|otf|png|woff2?)$/,
|
||||
use: [
|
||||
{
|
||||
loader: "file-loader",
|
||||
options: {
|
||||
name: production ? "[name].[hash].[ext]" : "[path][name].[ext]",
|
||||
outputPath: "files/",
|
||||
},
|
||||
},
|
||||
],
|
||||
type: "asset/resource",
|
||||
},
|
||||
],
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(__dirname, "static/webpack-bundles"),
|
||||
publicPath: "",
|
||||
filename: production ? "[name].[contenthash].js" : "[name].js",
|
||||
assetModuleFilename: production
|
||||
? "files/[name].[hash][ext][query]"
|
||||
: // Avoid directory traversal bug that upstream won't fix
|
||||
// (https://github.com/webpack/webpack/issues/11937)
|
||||
(pathData) => "files" + path.join("/", pathData.filename!),
|
||||
chunkFilename: production ? "[contenthash].js" : "[id].js",
|
||||
},
|
||||
resolve: {
|
||||
...baseConfig.resolve,
|
||||
extensions: [".ts", ".js"],
|
||||
},
|
||||
// We prefer cheap-module-source-map over any eval-* options
|
||||
|
@ -180,27 +177,9 @@ export default (env: {minimize?: boolean} = {}, argv: {mode?: string}): webpack.
|
|||
minimize: env.minimize ?? production,
|
||||
minimizer: [
|
||||
new CssMinimizerPlugin({
|
||||
sourceMap: true,
|
||||
minify: (data: Record<string, string>, sourceMap) => {
|
||||
// css-minimizer-webpack-plugin needs this require
|
||||
// inside the function.
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-imports, @typescript-eslint/no-var-requires
|
||||
const CleanCSS: typeof import("clean-css") = require("clean-css");
|
||||
const [[filename, styles]] = Object.entries(data);
|
||||
const out = new CleanCSS({sourceMap: true}).minify({
|
||||
[filename]: {styles, sourceMap},
|
||||
});
|
||||
return {
|
||||
css: out.styles,
|
||||
map: out.sourceMap.toString(),
|
||||
warnings: out.warnings,
|
||||
};
|
||||
},
|
||||
}),
|
||||
new TerserPlugin({
|
||||
cache: true,
|
||||
parallel: true,
|
||||
minify: CssMinimizerPlugin.cleanCssMinify,
|
||||
}),
|
||||
"...",
|
||||
],
|
||||
splitChunks: {
|
||||
chunks: "all",
|
||||
|
@ -215,13 +194,10 @@ export default (env: {minimize?: boolean} = {}, argv: {mode?: string}): webpack.
|
|||
filename: production
|
||||
? "webpack-stats-production.json"
|
||||
: "var/webpack-stats-dev.json",
|
||||
relativePath: true,
|
||||
}),
|
||||
...(production
|
||||
? []
|
||||
: [
|
||||
// Better logging from console for hot reload
|
||||
new webpack.NamedModulesPlugin(),
|
||||
// script-loader should load sourceURL in dev
|
||||
new webpack.LoaderOptionsPlugin({debug: true}),
|
||||
]),
|
||||
|
@ -259,18 +235,16 @@ export default (env: {minimize?: boolean} = {}, argv: {mode?: string}): webpack.
|
|||
};
|
||||
|
||||
const serverConfig: webpack.Configuration = {
|
||||
...baseConfig,
|
||||
name: "server",
|
||||
mode: production ? "production" : "development",
|
||||
target: "node",
|
||||
context: __dirname,
|
||||
entry: {
|
||||
"katex-cli": "shebang-loader!katex/cli",
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(__dirname, "static/webpack-bundles"),
|
||||
filename: "[name].js",
|
||||
},
|
||||
};
|
||||
|
||||
return [config, serverConfig];
|
||||
return [frontendConfig, serverConfig];
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue