fixed. 演练场静态打包问题

This commit is contained in:
q
2026-01-04 09:29:20 +08:00
parent d8f0dc4f8e
commit 8127cd0758
8 changed files with 195 additions and 21 deletions

17
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
version: 2
updates:
- package-ecosystem: "maven"
directory: "/"
open-pull-requests-limit: 10
ignore:
# 忽略通过 BOM 管理的 Vert.x 依赖
# 这些依赖的版本通过 vertx-dependencies BOM 统一管理
# 应该通过更新 pom.xml 中的 vertx.version 属性来更新这些依赖
- dependency-name: "io.vertx:vertx-web"
- dependency-name: "io.vertx:vertx-codegen"
- dependency-name: "io.vertx:vertx-config"
- dependency-name: "io.vertx:vertx-config-yaml"
- dependency-name: "io.vertx:vertx-service-proxy"
- dependency-name: "io.vertx:vertx-web-proxy"
- dependency-name: "io.vertx:vertx-web-client"

View File

@@ -128,7 +128,9 @@ public class ReverseProxyVerticle extends AbstractVerticle {
} }
private HttpServer getHttpsServer(JsonObject proxyConf) { private HttpServer getHttpsServer(JsonObject proxyConf) {
HttpServerOptions httpServerOptions = new HttpServerOptions(); HttpServerOptions httpServerOptions = new HttpServerOptions()
.setCompressionSupported(true);
if (proxyConf.containsKey("ssl")) { if (proxyConf.containsKey("ssl")) {
JsonObject sslConfig = proxyConf.getJsonObject("ssl"); JsonObject sslConfig = proxyConf.getJsonObject("ssl");
@@ -182,6 +184,7 @@ public class ReverseProxyVerticle extends AbstractVerticle {
} else { } else {
staticHandler = StaticHandler.create(); staticHandler = StaticHandler.create();
} }
if (staticConf.containsKey("directory-listing")) { if (staticConf.containsKey("directory-listing")) {
staticHandler.setDirectoryListing(staticConf.getBoolean("directory-listing")); staticHandler.setDirectoryListing(staticConf.getBoolean("directory-listing"));
} else if (staticConf.containsKey("index")) { } else if (staticConf.containsKey("index")) {

View File

@@ -3,6 +3,7 @@ module.exports = {
'@vue/cli-plugin-babel/preset' '@vue/cli-plugin-babel/preset'
], ],
plugins: [ plugins: [
'@vue/babel-plugin-transform-vue-jsx' '@vue/babel-plugin-transform-vue-jsx',
'@babel/plugin-transform-class-static-block'
] ]
} }

View File

@@ -5,7 +5,8 @@
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "serve": "vue-cli-service serve",
"dev": "vue-cli-service serve", "dev": "vue-cli-service serve",
"build": "vue-cli-service build", "build": "vue-cli-service build && node scripts/compress-vs.js",
"build:no-compress": "vue-cli-service build",
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {
@@ -28,6 +29,7 @@
"@babel/core": "^7.26.0", "@babel/core": "^7.26.0",
"@babel/eslint-parser": "^7.25.9", "@babel/eslint-parser": "^7.25.9",
"@babel/plugin-transform-class-properties": "^7.26.0", "@babel/plugin-transform-class-properties": "^7.26.0",
"@babel/plugin-transform-class-static-block": "^7.26.0",
"@vue/babel-plugin-transform-vue-jsx": "^1.4.0", "@vue/babel-plugin-transform-vue-jsx": "^1.4.0",
"@vue/cli-plugin-babel": "~5.0.8", "@vue/cli-plugin-babel": "~5.0.8",
"@vue/cli-plugin-eslint": "~5.0.8", "@vue/cli-plugin-eslint": "~5.0.8",
@@ -35,7 +37,8 @@
"compression-webpack-plugin": "^11.1.0", "compression-webpack-plugin": "^11.1.0",
"eslint": "^9.0.0", "eslint": "^9.0.0",
"eslint-plugin-vue": "^9.30.0", "eslint-plugin-vue": "^9.30.0",
"filemanager-webpack-plugin": "8.0.0" "filemanager-webpack-plugin": "8.0.0",
"monaco-editor-webpack-plugin": "^7.1.1"
}, },
"eslintConfig": { "eslintConfig": {
"root": true, "root": true,

124
web-front/scripts/compress-vs.js Executable file
View File

@@ -0,0 +1,124 @@
#!/usr/bin/env node
const path = require("path");
const fs = require("fs");
const zlib = require("zlib");
const { promisify } = require("util");
const gzip = promisify(zlib.gzip);
const readdir = promisify(fs.readdir);
const stat = promisify(fs.stat);
const readFile = promisify(fs.readFile);
const writeFile = promisify(fs.writeFile);
// 递归压缩目录下的所有文件
async function compressDirectory(dirPath, threshold = 1024) {
if (!fs.existsSync(dirPath)) {
console.warn(`目录不存在: ${dirPath}`);
return;
}
const files = await readdir(dirPath, { withFileTypes: true });
let compressedCount = 0;
let totalOriginalSize = 0;
let totalCompressedSize = 0;
for (const file of files) {
const filePath = path.join(dirPath, file.name);
if (file.isDirectory()) {
await compressDirectory(filePath, threshold);
} else if (file.isFile()) {
const stats = await stat(filePath);
// 只压缩超过阈值且不是已压缩的文件
if (stats.size > threshold && !filePath.endsWith('.gz') && !filePath.endsWith('.map')) {
try {
const content = await readFile(filePath);
const compressed = await gzip(content);
await writeFile(filePath + '.gz', compressed);
compressedCount++;
totalOriginalSize += stats.size;
totalCompressedSize += compressed.length;
console.log(`${file.name} (${(stats.size / 1024).toFixed(2)}KB -> ${(compressed.length / 1024).toFixed(2)}KB)`);
} catch (error) {
console.warn(`⚠ 压缩失败: ${filePath}`, error.message);
}
}
}
}
if (compressedCount > 0) {
console.log(`\n压缩完成: ${compressedCount} 个文件`);
console.log(`原始大小: ${(totalOriginalSize / 1024 / 1024).toFixed(2)}MB`);
console.log(`压缩后大小: ${(totalCompressedSize / 1024 / 1024).toFixed(2)}MB`);
console.log(`压缩率: ${((1 - totalCompressedSize / totalOriginalSize) * 100).toFixed(1)}%`);
}
}
// 删除未使用的 worker 文件
function deleteUnusedWorkers() {
const jsDir = path.join(__dirname, '../nfd-front/js');
const workers = ['editor.worker.js', 'editor.worker.js.gz', 'json.worker.js', 'json.worker.js.gz', 'ts.worker.js', 'ts.worker.js.gz'];
let deletedCount = 0;
for (const worker of workers) {
const filePath = path.join(jsDir, worker);
if (fs.existsSync(filePath)) {
try {
fs.unlinkSync(filePath);
deletedCount++;
console.log(`✓ 已删除未使用的文件: ${worker}`);
} catch (error) {
console.warn(`⚠ 删除失败: ${worker}`, error.message);
}
}
}
if (deletedCount > 0) {
console.log(`\n已删除 ${deletedCount} 个未使用的 worker 文件\n`);
}
}
// 复制到 webroot
function copyToWebroot() {
const source = path.join(__dirname, '../nfd-front');
const dest = path.join(__dirname, '../../webroot/nfd-front');
// 使用 FileManagerPlugin 的方式,这里用简单的复制
const { execSync } = require('child_process');
try {
// 删除目标目录
if (fs.existsSync(dest)) {
execSync(`rm -rf "${dest}"`, { stdio: 'inherit' });
}
// 复制整个目录
execSync(`cp -R "${source}" "${dest}"`, { stdio: 'inherit' });
console.log('\n✓ 已复制到 webroot');
} catch (error) {
console.error('\n✗ 复制到 webroot 失败:', error.message);
process.exit(1);
}
}
// 主函数
async function main() {
// 先删除未使用的 worker 文件
deleteUnusedWorkers();
// 然后压缩 vs 目录
const vsPath = path.join(__dirname, '../nfd-front/js/vs');
console.log('开始压缩 vs 目录下的文件...\n');
try {
await compressDirectory(vsPath, 1024); // 只压缩超过1KB的文件
console.log('\n✓ vs 目录压缩完成');
} catch (error) {
console.error('\n✗ vs 目录压缩失败:', error);
process.exit(1);
}
// 最后复制到 webroot
copyToWebroot();
}
main();

View File

@@ -94,13 +94,18 @@ export default {
return; return;
} }
// 配置Monaco Editor使用国内CDN (npmmirror) // 配置Monaco Editor使用本地打包的文件而不是CDN
// npmmirror的路径格式: https://registry.npmmirror.com/包名/版本号/files/文件路径 if (loader.config) {
loader.config({ const vsPath = process.env.NODE_ENV === 'production'
paths: { ? './js/vs' // 生产环境使用相对路径
vs: 'https://registry.npmmirror.com/monaco-editor/0.55.1/files/min/vs' : '/js/vs'; // 开发环境使用绝对路径
}
}); loader.config({
paths: {
vs: vsPath
}
});
}
// 初始化Monaco Editor // 初始化Monaco Editor
monaco = await loader.init(); monaco = await loader.init();

View File

@@ -1062,12 +1062,18 @@ function parseById(shareLinkInfo, http, logger) {
return; return;
} }
// 配置Monaco Editor使用国内CDN (npmmirror) // 配置Monaco Editor使用本地打包的文件而不是CDN
loader.config({ if (loader.config) {
paths: { const vsPath = process.env.NODE_ENV === 'production'
vs: 'https://registry.npmmirror.com/monaco-editor/0.55.1/files/min/vs' ? './js/vs' // 生产环境使用相对路径
} : '/js/vs'; // 开发环境使用绝对路径
});
loader.config({
paths: {
vs: vsPath
}
});
}
const monaco = await loader.init(); const monaco = await loader.init();
if (monaco) { if (monaco) {

View File

@@ -4,8 +4,10 @@ const path = require("path");
function resolve(dir) { function resolve(dir) {
return path.join(__dirname, dir) return path.join(__dirname, dir)
} }
const CompressionPlugin = require('compression-webpack-plugin'); const CompressionPlugin = require('compression-webpack-plugin');
const FileManagerPlugin = require('filemanager-webpack-plugin') const FileManagerPlugin = require('filemanager-webpack-plugin');
const MonacoEditorPlugin = require('monaco-editor-webpack-plugin');
module.exports = { module.exports = {
productionSourceMap: false, // 是否在构建生产包时生成sourceMap文件false将提高构建速度 productionSourceMap: false, // 是否在构建生产包时生成sourceMap文件false将提高构建速度
@@ -43,7 +45,7 @@ module.exports = {
'@': resolve('src') '@': resolve('src')
} }
}, },
// Monaco Editor配置 - 使用国内CDN // Monaco Editor配置 - 使用本地打包
module: { module: {
rules: [ rules: [
{ {
@@ -53,9 +55,18 @@ module.exports = {
] ]
}, },
plugins: [ plugins: [
new MonacoEditorPlugin({
languages: ['javascript', 'typescript', 'json'],
features: ['coreCommands', 'find', 'format', 'suggest', 'quickCommand'],
publicPath: process.env.NODE_ENV === 'production' ? './' : '/',
// Worker 文件输出路径
filename: 'js/[name].worker.js'
}),
new CompressionPlugin({ new CompressionPlugin({
test: /\.js$|\.html$|\.css/, // 匹配文件 test: /\.js$|\.html$|\.css/, // 匹配文件
threshold: 10240 // 对超过10k文件压缩 threshold: 10240, // 对超过10k文件压缩
// 排除 js 目录下的 worker 文件Monaco Editor 使用 vs/assets 下的)
exclude: /js\/.*\.worker\.js$/
}), }),
new FileManagerPlugin({ //初始化 filemanager-webpack-plugin 插件实例 new FileManagerPlugin({ //初始化 filemanager-webpack-plugin 插件实例
events: { events: {
@@ -70,7 +81,11 @@ module.exports = {
{ source: '../webroot/nfd-front/view/.gitignore', options: { force: true } }, { source: '../webroot/nfd-front/view/.gitignore', options: { force: true } },
], ],
copy: [ copy: [
{ source: './nfd-front', destination: '../webroot/nfd-front' } // 复制 Monaco Editor 的 vs 目录到 js/vs
{
source: './node_modules/monaco-editor/min/vs',
destination: './nfd-front/js/vs'
}
], ],
archive: [ //然后我们选择dist文件夹将之打包成dist.zip并放在根目录 archive: [ //然后我们选择dist文件夹将之打包成dist.zip并放在根目录
{ {