refactor(archiver): 优化打包插件逻辑并支持更多压缩格式
重构打包插件以支持多种压缩格式(zip, tar, tgz),并增加时间戳选项。同时,将插件调用移至VS Code终端检测逻辑中,确保仅在VS Code环境中执行
This commit is contained in:
@ -1,85 +1,117 @@
|
||||
// https://github.com/vbenjs/vue-vben-admin/blob/03ceb2aac5a47d7127562f2855d41da5c58b81bf/internal/vite-config/src/plugins/archiver.ts
|
||||
|
||||
import type { Plugin } from 'vite';
|
||||
|
||||
import archiver from 'archiver';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { createLogger } from 'vite';
|
||||
|
||||
interface ArchiverOptions {
|
||||
/**
|
||||
* 是否添加时间戳到输出文件名
|
||||
* @default false
|
||||
*/
|
||||
addTimestamp?: boolean;
|
||||
/**
|
||||
* 压缩格式,支持 'zip', 'tar', 'tgz'
|
||||
* @default 'zip'
|
||||
*/
|
||||
format?: 'tar' | 'tgz' | 'zip';
|
||||
/**
|
||||
* 输出目录
|
||||
* @default ''
|
||||
*/
|
||||
outputDir?: string;
|
||||
/**
|
||||
* 输出的zip文件名(不含扩展名)
|
||||
* 输出的文件名(不含扩展名)
|
||||
* @default 'dist'
|
||||
*/
|
||||
outputFileName?: string;
|
||||
/**
|
||||
* 要打包的源目录
|
||||
* 要打包的源目录,可以是单个目录或目录数组
|
||||
* @default 'dist'
|
||||
*/
|
||||
sourceDir?: string;
|
||||
sourceDir?: string | string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于将构建输出打包成zip文件的Vite插件
|
||||
* 用于将构建输出打包成压缩文件的Vite插件
|
||||
*/
|
||||
export function viteArchiverPlugin(options: ArchiverOptions = {}): Plugin {
|
||||
const { outputDir = '', outputFileName = 'dist', sourceDir = 'dist' } = options;
|
||||
const { addTimestamp = false, format = 'zip', outputDir = '', outputFileName = 'dist', sourceDir = 'dist' } = options;
|
||||
|
||||
// 创建Vite日志记录器
|
||||
const logger = createLogger();
|
||||
|
||||
return {
|
||||
apply: 'build',
|
||||
closeBundle: async () => {
|
||||
const sourcePath = path.resolve(process.cwd(), sourceDir);
|
||||
// 处理单个目录或目录数组
|
||||
const sourceDirs = Array.isArray(sourceDir) ? sourceDir : [sourceDir];
|
||||
const sourcePaths = sourceDirs.map((dir) => path.resolve(process.cwd(), dir));
|
||||
|
||||
// 检查源目录是否存在
|
||||
if (!fs.existsSync(sourcePath)) {
|
||||
console.error(`Source directory '${sourceDir}' does not exist.`);
|
||||
// 检查所有源目录是否存在
|
||||
const nonExistentDirs = sourcePaths.filter((dir) => !fs.existsSync(dir));
|
||||
if (nonExistentDirs.length > 0) {
|
||||
logger.error(`Source directories do not exist: ${nonExistentDirs.join(', ')}`);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info(`Creating archive from: ${sourceDirs.join(', ')}`);
|
||||
|
||||
// 如果输出目录不存在,则创建它
|
||||
const outputPath = path.resolve(process.cwd(), outputDir);
|
||||
if (outputDir && !fs.existsSync(outputPath)) {
|
||||
fs.mkdirSync(outputPath, { recursive: true });
|
||||
}
|
||||
|
||||
const outputFilePath = path.join(outputPath, `${outputFileName}.zip`);
|
||||
// 生成文件名,可选添加时间戳
|
||||
let finalFileName = outputFileName;
|
||||
if (addTimestamp) {
|
||||
const now = new Date();
|
||||
const timestamp = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}-${String(now.getHours()).padStart(2, '0')}${String(now.getMinutes()).padStart(2, '0')}${String(now.getSeconds()).padStart(2, '0')}`;
|
||||
finalFileName = `${outputFileName}-${timestamp}`;
|
||||
}
|
||||
|
||||
// 根据格式确定文件扩展名
|
||||
const fileExtension = format === 'zip' ? 'zip' : format === 'tar' ? 'tar' : 'tar.gz';
|
||||
const outputFilePath = path.join(outputPath, `${finalFileName}.${fileExtension}`);
|
||||
const output = fs.createWriteStream(outputFilePath);
|
||||
const archive = archiver('zip', {
|
||||
zlib: { level: 9 }, // 设置压缩级别
|
||||
|
||||
// 创建适当格式的归档器
|
||||
const archive = archiver(format === 'tgz' ? 'tar' : format, {
|
||||
gzip: format === 'tgz',
|
||||
...(format === 'zip' ? { zlib: { level: 9 } } : {}),
|
||||
});
|
||||
|
||||
// 监听所有归档数据写入完成
|
||||
output.on('close', () => {
|
||||
console.log(`Archive created: ${outputFilePath}`);
|
||||
console.log(`Total bytes: ${archive.pointer()}`);
|
||||
logger.info(`Archive created: ${outputFilePath}`);
|
||||
});
|
||||
|
||||
// 良好实践:捕获警告(例如stat失败和其他非阻塞错误)
|
||||
// 错误处理
|
||||
archive.on('warning', (err) => {
|
||||
if (err.code === 'ENOENT') {
|
||||
console.warn(err);
|
||||
logger.warn(`Warning during archiving: ${err.message}`);
|
||||
} else {
|
||||
logger.error(`Error during archiving: ${err.message}`);
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
|
||||
// 良好实践:明确捕获此错误
|
||||
archive.on('error', (err) => {
|
||||
logger.error(`Fatal error during archiving: ${err.message}`);
|
||||
throw err;
|
||||
});
|
||||
|
||||
// 将归档数据通过管道传输到文件
|
||||
archive.pipe(output);
|
||||
|
||||
// 从目录添加文件到归档
|
||||
archive.directory(sourcePath, false);
|
||||
// 添加文件到归档
|
||||
for (const sourcePath of sourcePaths) {
|
||||
archive.directory(sourcePath, false);
|
||||
}
|
||||
|
||||
// 完成归档(即我们已完成添加文件,但流尚未结束)
|
||||
// 完成归档
|
||||
await archive.finalize();
|
||||
},
|
||||
name: 'vite-plugin-archiver',
|
||||
|
Reference in New Issue
Block a user