Explorar o código

update 替代有问题的插件

疯狂的狮子Li hai 3 meses
pai
achega
ef5ea98a03
Modificáronse 2 ficheiros con 104 adicións e 23 borrados
  1. 0 1
      package.json
  2. 104 22
      vite/plugins/compression.ts

+ 0 - 1
package.json

@@ -74,7 +74,6 @@
     "unplugin-vue-components": "31.0.0",
     "unplugin-vue-setup-extend-plus": "1.0.1",
     "vite": "7.3.1",
-    "vite-plugin-compression": "0.5.1",
     "vite-plugin-svg-icons-ng": "^1.5.2",
     "vite-plugin-vue-devtools": "8.0.7",
     "vitest": "4.0.18",

+ 104 - 22
vite/plugins/compression.ts

@@ -1,28 +1,110 @@
-import compression from 'vite-plugin-compression';
+import { promises as fs } from 'fs';
+import path from 'path';
+import zlib from 'zlib';
+import { promisify } from 'util';
+import type { Plugin, ResolvedConfig } from 'vite';
 
-export default (env: any) => {
-  const { VITE_BUILD_COMPRESS } = env;
-  const plugin: any[] = [];
-  if (VITE_BUILD_COMPRESS) {
-    const compressList = VITE_BUILD_COMPRESS.split(',');
-    if (compressList.includes('gzip')) {
-      // http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件
-      plugin.push(
-        compression({
-          ext: '.gz',
-          deleteOriginFile: false
-        })
-      );
-    }
-    if (compressList.includes('brotli')) {
-      plugin.push(
-        compression({
-          ext: '.br',
-          algorithm: 'brotliCompress',
-          deleteOriginFile: false
+const gzip = promisify(zlib.gzip);
+const brotliCompress = promisify(zlib.brotliCompress);
+const compressibleFileRE = /\.(js|mjs|json|css|html)$/i;
+const defaultThreshold = 1025;
+
+type CompressionKind = 'gzip' | 'brotli';
+
+const compressionHandlers: Record<CompressionKind, { ext: string; compress: (content: Buffer) => Promise<Buffer> }> = {
+  gzip: {
+    ext: '.gz',
+    compress: (content) => gzip(content, { level: zlib.constants.Z_BEST_COMPRESSION })
+  },
+  brotli: {
+    ext: '.br',
+    compress: (content) =>
+      brotliCompress(content, {
+        params: {
+          [zlib.constants.BROTLI_PARAM_QUALITY]: zlib.constants.BROTLI_MAX_QUALITY,
+          [zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT
+        }
+      })
+  }
+};
+
+async function collectFiles(rootDir: string): Promise<string[]> {
+  const entries = await fs.readdir(rootDir, { withFileTypes: true });
+  const files = await Promise.all(
+    entries.map(async (entry) => {
+      const fullPath = path.join(rootDir, entry.name);
+      if (entry.isDirectory()) {
+        return collectFiles(fullPath);
+      }
+      return compressibleFileRE.test(entry.name) ? [fullPath] : [];
+    })
+  );
+  return files.flat();
+}
+
+function createCompressionPlugin(kind: CompressionKind): Plugin {
+  const handler = compressionHandlers[kind];
+  let config: ResolvedConfig | undefined;
+
+  return {
+    name: `local:compression:${kind}`,
+    apply: 'build',
+    enforce: 'post',
+    configResolved(resolvedConfig) {
+      config = resolvedConfig;
+    },
+    async closeBundle() {
+      const outputDir = path.resolve(process.cwd(), config?.build.outDir ?? 'dist');
+      const files = await collectFiles(outputDir);
+      const compressedEntries: Array<{ file: string; originalKb: string; compressedKb: string }> = [];
+
+      await Promise.all(
+        files.map(async (filePath) => {
+          const stat = await fs.stat(filePath);
+          if (stat.size < defaultThreshold) {
+            return;
+          }
+
+          const content = await fs.readFile(filePath);
+          const compressed = await handler.compress(content);
+          const outputFile = `${filePath}${handler.ext}`;
+
+          await fs.writeFile(outputFile, compressed);
+          compressedEntries.push({
+            file: path.relative(outputDir, outputFile).replaceAll('\\', '/'),
+            originalKb: (stat.size / 1024).toFixed(2),
+            compressedKb: (compressed.byteLength / 1024).toFixed(2)
+          });
         })
       );
+
+      if (!compressedEntries.length) {
+        return;
+      }
+
+      compressedEntries.sort((a, b) => a.file.localeCompare(b.file));
+      config?.logger.info(`\n[compression:${kind}] generated ${compressedEntries.length} files`);
+      for (const entry of compressedEntries) {
+        config?.logger.info(`${path.basename(outputDir)}/${entry.file} ${entry.originalKb}kb -> ${entry.compressedKb}kb`);
+      }
+      config?.logger.info('');
     }
+  };
+}
+
+export default (env: Record<string, string>) => {
+  const { VITE_BUILD_COMPRESS } = env;
+  const plugins: Plugin[] = [];
+  if (!VITE_BUILD_COMPRESS) {
+    return plugins;
+  }
+
+  const compressionList = VITE_BUILD_COMPRESS.split(',').map((item) => item.trim()) as CompressionKind[];
+  if (compressionList.includes('gzip')) {
+    plugins.push(createCompressionPlugin('gzip'));
+  }
+  if (compressionList.includes('brotli')) {
+    plugins.push(createCompressionPlugin('brotli'));
   }
-  return plugin;
+  return plugins;
 };