ui: upgrade to webpack5

This commit is contained in:
undefined committed 2022-08-07 03:15:36 +08:00
1 parent 8648929063
commit a05125c6b0
134 files changed
+503 -457

No files matched your search

@@ -1,25 +1,21 @@
/* eslint-disable global-require */
/* eslint-disable import/no-extraneous-dependencies */
import { dirname } from 'path';
import webpack from 'webpack';
import { CleanWebpackPlugin } from 'clean-webpack-plugin';
import CopyWebpackPlugin from 'copy-webpack-plugin';
import { ESBuildMinifyPlugin } from 'esbuild-loader';
import FriendlyErrorsPlugin from 'friendly-errors-webpack-plugin';
import ExtractCssPlugin from 'mini-css-extract-plugin';
import MonacoWebpackPlugin from 'monaco-editor-webpack-plugin';
import FriendlyErrorsPlugin from 'friendly-errors-webpack-plugin';
import CopyWebpackPlugin from 'copy-webpack-plugin';
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
import { dirname } from 'path';
import SpeedMeasurePlugin from 'speed-measure-webpack-plugin';
import webpack from 'webpack';
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
import WebpackBar from 'webpackbar';
import mapWebpackUrlPrefix from '../utils/mapWebpackUrlPrefix';
import root from '../utils/root';
const beautifyOutputUrl = mapWebpackUrlPrefix([
{ prefix: 'misc/.iconfont', replace: './ui/iconfont' },
]);
const smp = new SpeedMeasurePlugin();
export default function (env = {}) {
export default function (env: { production?: boolean, measure?: boolean } = {}) {
function esbuildLoader() {
return {
loader: 'esbuild-loader',
@@ -41,28 +37,7 @@ export default function (env = {}) {
function postcssLoader() {
return {
loader: 'postcss-loader',
options: { sourceMap: env.production, config: { path: root('postcss.config.js') } },
};
}
function fileLoader() {
return {
loader: 'file-loader',
options: {
name(resourcePath) {
if (resourcePath.includes('node_modules')) {
const extra = resourcePath.split('node_modules')[1];
const moduleName = extra.split('/')[0];
if (extra.includes('@fontsource')) {
return `fonts/${extra.substr(2).replace(/\\/g, '/')}?[contenthash]`;
}
if (['katex', 'monaco-editor'].includes(moduleName)) return `modules/${moduleName}/[name].[ext]?[contenthash]`;
return `modules/${extra.substr(1).replace(/\\/g, '/')}?[contenthash]`;
}
if (resourcePath.includes('misc/.iconfont')) return 'modules/icon/[name].[ext]?[contenthash]';
return '[path][name].[ext]?[contenthash]';
},
},
options: { postcssOptions: { sourceMap: env.production, config: root('postcss.config.js') } },
};
}
@@ -76,24 +51,45 @@ export default function (env = {}) {
};
}
const config = {
bail: true,
function stylusLoader() {
return {
loader: 'stylus-loader',
options: {
stylusOptions: {
preferPathResolver: 'webpack',
use: [require('rupture')()], // eslint-disable-line global-require
import: ['~vj/common/common.inc.styl'],
},
},
};
}
const config: import('webpack').Configuration = {
// bail: !env.production,
mode: (env.production || env.measure) ? 'production' : 'development',
profile: true,
profile: env.measure,
context: root(),
stats: {
preset: 'errors-warnings',
},
devtool: env.production ? 'source-map' : false,
entry: {
hydro: './entry.js',
polyfill: './polyfill.ts',
'default.theme': './theme/default.js',
},
cache: {
type: 'filesystem',
cacheDirectory: root('../../.cache'),
idleTimeout: 30000,
},
output: {
path: root('public'),
publicPath: '/', // overwrite in entry.js
hashFunction: 'sha1',
hashDigest: 'hex',
hashDigestLength: 10,
filename: '[name].js?[hash]',
filename: '[name].js?[contenthash]',
chunkFilename: '[name].[chunkhash].chunk.js',
},
resolve: {
@@ -114,33 +110,60 @@ export default function (env = {}) {
use: { loader: '@svgr/webpack', options: { icon: true } },
},
{
use: [fileLoader()],
type: 'asset/resource',
},
],
},
{
test: /\.(ttf|eot|woff|woff2|png|jpg|jpeg|gif)$/,
use: [fileLoader()],
type: 'asset/resource',
generator: {
filename: (pathData) => {
const p = pathData.module.resource.replace(/\\/g, '/');
const filename = p.split('/').pop();
if (p.includes('node_modules')) {
const extra = p.split('node_modules')[1];
const moduleName = extra.split('/')[0];
if (extra.includes('@fontsource')) {
return `fonts/${filename}?[hash]`;
}
if (['katex', 'monaco-editor'].includes(moduleName)) {
return `modules/${moduleName}/${filename}?[hash]`;
}
return `modules/${extra.substr(1)}?[hash]`;
}
if (p.includes('.iconfont')) return `${filename}?[hash]`;
return `${p.split('ui-default')[1].substring(1)}?[hash]`;
},
},
},
{
test: /\.ts$/,
include: /@types\//,
type: 'asset/inline',
generator: {
dataUrl: (buf) => buf.toString(),
},
},
{
test: /\.[jt]sx?$/,
exclude: /@types\//,
use: [esbuildLoader()],
},
{
test: /\.styl$/,
use: [extractCssLoader(), cssLoader(), postcssLoader(), 'stylus-loader'],
use: [extractCssLoader(), cssLoader(), postcssLoader(), stylusLoader()],
},
{
test: /\.css$/,
use: [extractCssLoader(), cssLoader(), postcssLoader()],
},
{
test: /\.wasm$/,
use: [fileLoader()],
type: 'javascript/auto',
},
],
},
experiments: {
asyncWebAssembly: true,
syncWebAssembly: true,
},
optimization: {
splitChunks: {
minSize: 256000,
@@ -149,7 +172,7 @@ export default function (env = {}) {
automaticNameDelimiter: '-',
cacheGroups: {
style: {
test: /\.(css|styl|less|sass|scss)$/,
test: /\.(css|styl|less|s[ac]ss)$/,
priority: 99,
name: 'style',
},
@@ -199,20 +222,10 @@ export default function (env = {}) {
monaco: 'monaco-editor/esm/vs/editor/editor.api',
}),
new ExtractCssPlugin({
filename: '[name].css?[hash:10]',
}),
new webpack.LoaderOptionsPlugin({
test: /\.styl$/,
stylus: {
default: {
preferPathResolver: 'webpack',
use: [require('rupture')()], // eslint-disable-line global-require
import: ['~vj/common/common.inc.styl'],
},
},
filename: '[name].css?[fullhash:10]',
}),
new FriendlyErrorsPlugin(),
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new webpack.IgnorePlugin({ resourceRegExp: /(^\.\/locale$|mathjax|abcjs)/ }),
new CopyWebpackPlugin({
patterns: [
{ from: root('static') },
@@ -221,16 +234,7 @@ export default function (env = {}) {
],
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: env.production ? '"production"' : '"debug"',
VERSION: JSON.stringify(require('@hydrooj/ui-default/package.json').version),
},
}),
new webpack.LoaderOptionsPlugin({
options: {
context: root(),
customInterpolateName: beautifyOutputUrl,
},
'process.env.VERSION': JSON.stringify(require('@hydrooj/ui-default/package.json').version),
}),
new webpack.NormalModuleReplacementPlugin(/\/(vscode-)?nls\.js/, require.resolve('../../components/monaco/nls')),
new MonacoWebpackPlugin({
+5 -12
View File
@@ -19,19 +19,17 @@ async function runWebpack({
}) {
const compiler = webpack(webpackConfig({ watch, production, measure }));
if (dev) {
const server = new WebpackDevServer(compiler, {
const server = new WebpackDevServer({
port: 8000,
compress: true,
hot: true,
disableHostCheck: true,
stats: 'none',
index: root('public'),
proxy: {
context: (path) => !path.includes('sockjs-node'),
context: (path) => path !== '/ws' && !path.startsWith('/vendors.js'),
target: 'http://localhost:2333',
ws: true,
},
});
return server.listen(8000);
}, compiler);
return server.start();
}
return new Promise((resolve, reject) => {
function compilerCallback(err, stats) {
@@ -85,15 +83,10 @@ async function main() {
if (fs.existsSync('public/polyfill.js')) {
fs.copyFileSync('public/polyfill.js', `public/polyfill-${pkg.version}.js`);
}
if (fs.existsSync('public/default.theme.css')) {
fs.copyFileSync('public/default.theme.css', `public/default-${pkg.version}.theme.css`);
}
if (argv.options.production) {
fs.removeSync('public/vditor/dist/js/mathjax');
fs.removeSync('public/vditor/dist/js/echarts');
fs.removeSync('public/vditor/dist/js/graphviz');
fs.removeSync('public/vditor/dist/js/mermaid');
fs.removeSync('public/vditor/dist/js/abcjs');
const files = fs.readdirSync('public');
files.filter((i) => /(^[in]\..+|worker)\.js\.map$/.test(i)).forEach((i) => fs.removeSync(`public/${i}`));
}
@@ -1,18 +0,0 @@
/* eslint-disable import/no-extraneous-dependencies */
import { escapeRegExp } from 'lodash';
export default function mapWebpackUrlPrefix(mapList) {
const rules = mapList.map((mappingRule) => {
const regex = mappingRule.prefix.split('/').map((s) => escapeRegExp(s)).join('[\\/\\\\]');
return {
from: new RegExp(`^${regex}`, mappingRule.flag),
to: mappingRule.replace,
};
});
return function mapUrl(url) {
rules.forEach((rule) => {
url = url.replace(rule.from, rule.to);
});
return url;
};
}