ui: use esbuild-loader & chunk-splitting

This commit is contained in:
undefined committed 2021-08-07 19:52:57 +08:00
1 parent db9def7917
commit e67c1c333a
9 files changed
+104 -54

No files matched your search

+49 -27
View File
@@ -1,10 +1,12 @@
/* 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 { ESBuildMinifyPlugin } from 'esbuild-loader';
import ExtractCssPlugin from 'mini-css-extract-plugin';
import MonacoWebpackPlugin from 'monaco-editor-webpack-plugin';
import FriendlyErrorsPlugin from 'friendly-errors-webpack-plugin';
import OptimizeCssAssetsPlugin from 'optimize-css-assets-webpack-plugin';
import CopyWebpackPlugin from 'copy-webpack-plugin';
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
import SpeedMeasurePlugin from 'speed-measure-webpack-plugin';
@@ -20,22 +22,13 @@ const beautifyOutputUrl = mapWebpackUrlPrefix([
const smp = new SpeedMeasurePlugin();
export default function (env = {}) {
function babelLoader() {
return {
loader: 'babel-loader',
options: {
...require(root('babel.config.js')), // eslint-disable-line
cacheDirectory: true,
},
};
}
function esbuildLoader() {
return {
loader: 'esbuild-loader',
options: {
loader: 'tsx',
target: 'es2015',
sourcemap: true,
},
};
}
@@ -113,13 +106,7 @@ export default function (env = {}) {
use: [fileLoader()],
},
{
test: /\.jsx?$/,
exclude: /node_modules[/\\]/,
use: [babelLoader()],
},
{
test: /\.tsx?$/,
exclude: /node_modules[/\\]/,
test: /\.[jt]sx?$/,
use: [esbuildLoader()],
},
{
@@ -139,14 +126,55 @@ export default function (env = {}) {
},
optimization: {
splitChunks: {
minSize: 80000,
maxAsyncRequests: 15,
maxInitialRequests: 10,
minSize: 256000,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '-',
cacheGroups: {
blockly: {
test: /[\\/]@?blockly[\\/]/,
priority: 10,
name: 'blockly',
},
monaco: {
test: /[\\/]monaco-editor[\\/]/,
priority: 9,
name: `monaco-${require('monaco-editor/package.json').version}`,
},
vditor: {
test: /[\\/]vditor[\\/]/,
priority: 8,
name: `vditor-${require('vditor/package.json').version}`,
},
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
name: 'vendors',
reuseExistingChunk: true,
},
default: {
priority: -20,
reuseExistingChunk: true,
},
},
},
minimizer: [new ESBuildMinifyPlugin({
css: true,
minify: true,
minifySyntax: true,
minifyWhitespace: true,
minifyIdentifiers: true,
treeShaking: true,
target: [
'chrome60',
],
exclude: [/mathmaps/, /\.min\.js$/],
})],
moduleIds: env.production ? 'size' : 'named',
chunkIds: env.production ? 'size' : 'named',
},
plugins: [
new CleanWebpackPlugin(),
new WebpackBar(),
new webpack.ProvidePlugin({
$: 'jquery',
@@ -183,12 +211,6 @@ export default function (env = {}) {
NODE_ENV: env.production ? '"production"' : '"debug"',
},
}),
...(env.production || env.measure)
? [
new OptimizeCssAssetsPlugin(),
new webpack.LoaderOptionsPlugin({ minimize: true }),
]
: [],
new webpack.LoaderOptionsPlugin({
options: {
context: root(),
@@ -1,9 +1,9 @@
/* eslint-disable import/no-extraneous-dependencies */
import _ from 'lodash';
import { escapeRegExp } from 'lodash';
export default function mapWebpackUrlPrefix(mapList) {
const rules = mapList.map((mappingRule) => {
const regex = mappingRule.prefix.split('/').map((s) => _.escapeRegExp(s)).join('[\\/\\\\]');
const regex = mappingRule.prefix.split('/').map((s) => escapeRegExp(s)).join('[\\/\\\\]');
return {
from: new RegExp(`^${regex}`, mappingRule.flag),
to: mappingRule.replace,
@@ -1,4 +1,4 @@
import _ from 'lodash';
import { assign } from 'lodash';
import tpl from 'vj/utils/tpl';
import request from 'vj/utils/request';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
@@ -40,5 +40,5 @@ export default class DomainSelectAutoComplete extends AutoComplete {
}
}
_.assign(DomainSelectAutoComplete, DOMAttachedObject);
assign(DomainSelectAutoComplete, DOMAttachedObject);
window.Hydro.components.DomainSelectAutoComplete = DomainSelectAutoComplete;
@@ -1,4 +1,4 @@
import _ from 'lodash';
import { assign } from 'lodash';
import tpl from 'vj/utils/tpl';
import request from 'vj/utils/request';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
@@ -37,5 +37,5 @@ export default class ProblemSelectAutoComplete extends AutoComplete {
}
}
_.assign(ProblemSelectAutoComplete, DOMAttachedObject);
assign(ProblemSelectAutoComplete, DOMAttachedObject);
window.Hydro.components.ProblemSelectAutoComplete = ProblemSelectAutoComplete;
@@ -1,5 +1,5 @@
import Drop from 'tether-drop';
import _ from 'lodash';
import { assign } from 'lodash';
import 'jquery-scroll-lock';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
@@ -194,5 +194,5 @@ export default class AutoComplete extends DOMAttachedObject {
}
}
_.assign(AutoComplete, DOMAttachedObject);
assign(AutoComplete, DOMAttachedObject);
window.Hydro.components.autocomplete = AutoComplete;
@@ -1,23 +1,28 @@
/*
To add a new language to highlight:
1. Add language in babel in package.json
2. Add new import statement in `components/cmeditor/vjcmeditor.js`
3. Add new import statement in `components/scratchpad/ScratchpadEditorContainer.js`
4. Add new meta data in `components/highlighter/meta.js`
*/
import Prism from 'prismjs';
import components from 'prismjs/components';
import getLoader from 'prismjs/dependencies';
import 'prismjs/plugins/toolbar/prism-toolbar';
import 'prismjs/plugins/toolbar/prism-toolbar.css';
import 'prismjs/plugins/line-numbers/prism-line-numbers';
import 'prismjs/plugins/line-numbers/prism-line-numbers.css';
import Clipboard from 'clipboard';
import Notification from 'vj/components/notification/index';
import i18n from 'vj/utils/i18n';
import languageMeta from './meta';
const languageExtMap = {};
const files = require.context('prismjs/components/', true, /prism-[a-z0-9-]+\.js/);
const loadedLanguages = new Set();
function loadLanguages() {
const languages = Object.keys(components.languages).filter((l) => l !== 'meta');
const loaded = [...loadedLanguages, ...Object.keys(Prism.languages)];
getLoader(components, languages, loaded).load((lang) => {
files(`./prism-${lang}.js`);
loadedLanguages.add(lang);
});
}
const languageExtMap = {};
loadLanguages();
// Map possible language names to Prism language name
languageMeta.forEach((meta) => {
for (let i = 0; i < meta.ext.length; ++i) {
@@ -1,5 +1,4 @@
import React from 'react';
import _ from 'lodash';
import { connect } from 'react-redux';
import TimeAgo from 'timeago-react';
import moment from 'dayjs';
@@ -55,7 +54,7 @@ export default connect(mapStateToProps)(class MessagePadDialogueContentContainer
renderInner() {
if (this.props.activeId === null) return [];
return _.map(this.props.item.messages, (msg) => (
return this.props.item.messages.map((msg) => (
<Message
key={msg._id}
isSelf={msg.from === UserContext._id}
@@ -1,6 +1,8 @@
import React from 'react';
import { connect } from 'react-redux';
import load from 'vj/components/wastyle/index';
import monaco from 'vj/components/monaco/index';
import Notification from 'vj/components/notification';
const mapStateToProps = (state) => ({
value: state.editor.code,
@@ -29,7 +31,7 @@ export default connect(mapStateToProps, mapDispatchToProps)(class MonacoEditor e
const { language, theme } = this.props;
if (this.props.language === 'blockly') {
if (!this.blockly) {
import('./blockly.jsx').then(({ default: Blockly }) => {
import('./blockly').then(({ default: Blockly }) => {
if (!this.blockly) return;
Blockly.inject(this.containerElement, {
});
@@ -51,6 +53,29 @@ export default connect(mapStateToProps, mapDispatchToProps)(class MonacoEditor e
const fontSize = localStorage.getItem('scratchpad.editor.fontSize');
if (fontSize && !Number.isNaN(+fontSize)) config.fontSize = +fontSize;
this.editor = monaco.editor.create(this.containerElement, config);
this.editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.KEY_P, () => {
this.editor.getAction('editor.action.quickCommand').run();
});
load().then(([loaded, format]) => {
if (!loaded) return;
const formatAction = {
id: 'hydro.format',
label: 'Format Code',
contextMenuOrder: 0,
contextMenuGroupId: 'operation',
keybindings: [monaco.KeyMod.Alt | monaco.KeyMod.Shift | monaco.KeyCode.KEY_F],
run: () => {
if (!['cpp', 'c'].includes(this.model._languageIdentifier.language)) return;
const [success, result] = format(this.editor.getValue(), `${UserContext.astyleOptions.trim()} mode=c`);
if (success) this.editor.setValue(result);
else Notification.warn(result);
},
};
this.editor.addAction(formatAction);
this.editor.addCommand(monaco.KeyMod.Alt | monaco.KeyMod.Shift | monaco.KeyCode.KEY_F, () => {
this.editor.getAction('hydro.format').run();
});
});
this.disposable.push(
this.editor.onDidChangeModelContent((event) => {
if (!this.__prevent_trigger_change_event) {
@@ -69,7 +94,7 @@ export default connect(mapStateToProps, mapDispatchToProps)(class MonacoEditor e
if (this.props.language === 'blockly') {
if (!this.blockly) {
this.editor.dispose();
import('./blockly.jsx').then(({ default: Blockly, toolbox }) => {
import('./blockly').then(({ default: Blockly, toolbox }) => {
if (!this.blockly) return;
Blockly.inject(this.containerElement, {
toolbox,
+1 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@hydrooj/ui-default",
"version": "4.15.2",
"version": "4.16.0",
"author": "undefined <i@undefined.moe>",
"license": "AGPL-3.0",
"main": "hydro.js",
@@ -75,7 +75,6 @@
"nanoid": "^3.1.23",
"normalize.css": "^8.0.1",
"nprogress": "^0.2.0",
"optimize-css-assets-webpack-plugin": "^5.0.8",
"pickadate": "^3.6.4",
"plugin-error": "^1.0.1",
"postcss-loader": "^3.0.0",