feat(All):Initial

This commit is contained in:
2025-10-04 23:36:07 +08:00
commit 2b4e5d2668
1321 changed files with 415958 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
export * from './utils.ts';
export * from './plugins/index.ts';
+28
View File
@@ -0,0 +1,28 @@
// @ts-ignore
import ConfigPlugin from 'unplugin-config/vite';
import type { PluginOption } from 'vite';
import {getEnvConfig,strToHex} from "../utils.ts";
export async function createConfigPluginConfig(
shouldGenerateConfig: boolean,
): Promise<PluginOption> {
const config:Record<string, any> = await getEnvConfig();
const APP_NAME = strToHex(config?.VITE_GLOB_APP_TITLE ?? '__APP');
// https://github.com/kirklin/unplugin-config
return ConfigPlugin({
appName: APP_NAME,
baseDir:"./",
envVariables: {
prefix: 'VITE_GLOB_',
files: [".env.production", ".env"],
},
configFile: {
generate: shouldGenerateConfig,
fileName: '_astral3d.config.js',
outputDir: 'dist',
},
htmlInjection: {
decodeEntities: true,
},
});
}
+36
View File
@@ -0,0 +1,36 @@
/**
* 用于打包和输出gzip;
* 注意,这在Vite中不能正常工作,具体原因还在调查中
* https://github.com/anncwb/vite-plugin-compression
*/
import type { PluginOption } from 'vite';
import compressPlugin from 'vite-plugin-compression';
export function configCompressPlugin({compress,deleteOriginFile = false}: {
compress: "gzip" | "brotli" | "none";
deleteOriginFile?: boolean;
}): PluginOption[] {
const compressList = compress.split(',');
const plugins: PluginOption[] = [];
if (compressList.includes('gzip')) {
plugins.push(
compressPlugin({
ext: '.gz',
deleteOriginFile,
}),
);
}
if (compressList.includes('brotli')) {
plugins.push(
compressPlugin({
ext: '.br',
algorithm: 'brotliCompress',
deleteOriginFile,
}),
);
}
return plugins;
}
+54
View File
@@ -0,0 +1,54 @@
import type {PluginOption} from 'vite';
import topLevelAwait from "vite-plugin-top-level-await";
import EnhanceLog from 'vite-plugin-enhance-log';
import {createConfigPluginConfig} from "./appConfig.ts";
import {configCompressPlugin} from "./compress.ts";
import {configVisualizerConfig} from "./visualizer.ts";
interface Options {
isBuild: boolean;
root: string;
compress: {
compress: "gzip" | "brotli" | "none";
deleteOriginFile: boolean;
};
enableAnalyze?: boolean;
enableConfig?: boolean;
}
export async function createPlugins({isBuild,compress,enableAnalyze,enableConfig}: Options) {
const vitePlugins: (PluginOption | PluginOption[])[] = [
topLevelAwait({
// 每个块模块的顶级await promise的导出名称
promiseExportName: "__tla",
// 用于在每个块模块中生成顶级await承诺的导入名称的函数
promiseImportName: i => `__tla_${i}`
}),
EnhanceLog({
/** 高亮文件名(firefox不支持) */
colorFileName: true,
splitBy: '\n',
preTip: '🚀🚀🚀🚀🚀🚀',
enableFileName: { enableDir: false}
}),
];
if(enableConfig){
const appConfigPlugin = await createConfigPluginConfig(isBuild);
vitePlugins.push(appConfigPlugin);
}
// 以下插件只在生产环境中工作
if (isBuild) {
// rollup-plugin-gzip
vitePlugins.push(configCompressPlugin(compress));
// 打包视图分析 rollup-plugin-visualizer
if (enableAnalyze) {
vitePlugins.push(configVisualizerConfig());
}
}
return vitePlugins;
}
+15
View File
@@ -0,0 +1,15 @@
/**
* package.json包文件容量分析
*/
// @ts-ignore
import {visualizer} from 'rollup-plugin-visualizer';
import { type PluginOption } from 'vite';
export function configVisualizerConfig() {
return visualizer({
filename: 'node_modules/.cache/visualizer/stats.html',
open: true,
gzipSize: true,
brotliSize: true,
}) as PluginOption;
}
+75
View File
@@ -0,0 +1,75 @@
import { join } from 'node:path';
import pkg from 'fs-extra';
import {parse} from "dotenv";
/**
* 读取所有环境变量配置文件以处理.env
*/
export function wrapperEnv(envConf) {
const ret:any = {};
for (const envName of Object.keys(envConf)) {
let realName = envConf[envName].replace(/\\n/g, '\n');
realName = realName === 'true' ? true : realName === 'false' ? false : realName;
if (envName === 'VITE_PORT') {
realName = Number(realName);
}
ret[envName] = realName;
if (typeof realName === 'string') {
process.env[envName] = realName;
} else if (typeof realName === 'object') {
process.env[envName] = JSON.stringify(realName);
}
}
return ret;
}
/**
* 获取当前环境下生效的配置文件名
*/
function getConfFiles() {
const script = process.env.npm_lifecycle_script;
const reg = new RegExp('--mode ([a-z_\\d]+)');
const result = reg.exec(script as string) as any;
if (result) {
const mode = result[1] as string;
return ['.env', `.env.${mode}`];
}
return ['.env', '.env.production'];
}
/**
* 获取以指定前缀开头的环境变量
* @param match prefix
* @param confFiles ext
*/
export async function getEnvConfig(match = 'VITE_GLOB_', confFiles = getConfFiles()) {
let envConfig = {};
for (const confFile of confFiles) {
try {
const envPath = await pkg.readFile(join(process.cwd(), confFile), { encoding: 'utf8' });
const env = parse(envPath);
envConfig = { ...envConfig, ...env };
} catch (e) {
console.error(`Error in parsing ${confFile}`, e);
}
}
const reg = new RegExp(`^(${match})`);
Object.keys(envConfig).forEach((key) => {
if (!reg.test(key)) {
Reflect.deleteProperty(envConfig, key);
}
});
return envConfig;
}
export function strToHex(str: string) {
const result: string[] = [];
for (let i = 0; i < str.length; ++i) {
const hex = str.charCodeAt(i).toString(16);
result.push(('000' + hex).slice(-4));
}
return result.join('').toUpperCase();
}