mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-14 21:20:48 +08:00
build(vite)!: migrate to Vite 8, switch to Oxc-based @vitejs/plugin-react, and clean up legacy compatibility config (#6492)
* chore(deps): update npm dependencies to v8 * build(vite)!: migrate to Vite 8, switch to Oxc-based @vitejs/plugin-react, and clean up legacy compatibility config --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Slinetrac <realakayuki@gmail.com>
This commit is contained in:
co-authored by
renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Slinetrac
parent
cb2e5bf603
commit
b707dd264e
+4
-201
@@ -1,152 +1,10 @@
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
import legacy from "@vitejs/plugin-legacy";
|
||||
import react from "@vitejs/plugin-react-swc";
|
||||
import react from "@vitejs/plugin-react";
|
||||
import { defineConfig } from "vite";
|
||||
import svgr from "vite-plugin-svgr";
|
||||
|
||||
const CONFIG_DIR = path.dirname(fileURLToPath(import.meta.url));
|
||||
const SRC_ROOT = path.resolve(CONFIG_DIR, "src");
|
||||
|
||||
const getPackageName = (id: string) => {
|
||||
// Walk through possible pnpm virtual paths and nested node_modules, return the last package segment.
|
||||
const matches = [
|
||||
...id.matchAll(
|
||||
/node_modules\/(?:\.pnpm\/[^/]+\/)?(?:node_modules\/)?((?:@[^/]+\/)?[^/]+)/g,
|
||||
),
|
||||
];
|
||||
const last = matches.at(-1);
|
||||
return last ? last[1] : null;
|
||||
};
|
||||
|
||||
const getSemanticNameFromFacade = (
|
||||
facadeModuleId: string | null | undefined,
|
||||
) => {
|
||||
if (!facadeModuleId) return null;
|
||||
|
||||
const cleanPath = facadeModuleId.split("?")[0];
|
||||
const relativePath = path.relative(SRC_ROOT, cleanPath);
|
||||
if (relativePath.startsWith("..")) return null;
|
||||
|
||||
const withoutExtension = relativePath.replace(/\.[^/.]+$/, "");
|
||||
const normalizedPath = withoutExtension.replace(/\\/g, "/");
|
||||
const withoutTrailingIndex = normalizedPath.endsWith("/index")
|
||||
? normalizedPath.slice(0, -"/index".length)
|
||||
: normalizedPath;
|
||||
|
||||
const semanticName = withoutTrailingIndex
|
||||
.split("/")
|
||||
.filter(Boolean)
|
||||
.join("-")
|
||||
.replace(/[^a-zA-Z0-9-]/g, "-")
|
||||
.replace(/--+/g, "-")
|
||||
.replace(/^-+|-+$/g, "");
|
||||
|
||||
return semanticName || "index";
|
||||
};
|
||||
|
||||
const normalizeEntryName = (name: string, isEntry?: boolean) =>
|
||||
isEntry && name === "index" ? "main" : name;
|
||||
|
||||
const getSemanticNameFromChunk = (chunkInfo: {
|
||||
facadeModuleId: string | null | undefined;
|
||||
moduleIds?: string[];
|
||||
name: string;
|
||||
isEntry?: boolean;
|
||||
}) => {
|
||||
const fromFacade = getSemanticNameFromFacade(chunkInfo.facadeModuleId);
|
||||
if (fromFacade) return normalizeEntryName(fromFacade, chunkInfo.isEntry);
|
||||
|
||||
if (Array.isArray(chunkInfo.moduleIds)) {
|
||||
for (const moduleId of chunkInfo.moduleIds) {
|
||||
const semantic = getSemanticNameFromFacade(moduleId);
|
||||
if (semantic) return normalizeEntryName(semantic, chunkInfo.isEntry);
|
||||
}
|
||||
}
|
||||
|
||||
return normalizeEntryName(chunkInfo.name, chunkInfo.isEntry);
|
||||
};
|
||||
|
||||
const normalizePackageName = (pkg: string) =>
|
||||
pkg.replace(/^@/, "").replace(/[@/]/g, "-");
|
||||
|
||||
type ChunkMatchContext = { id: string; pkg: string | null };
|
||||
type ChunkRule = {
|
||||
name: string | ((pkg: string) => string);
|
||||
match: (ctx: ChunkMatchContext) => boolean;
|
||||
};
|
||||
|
||||
const CHUNK_PACKAGE_SETS: Record<string, ReadonlySet<string>> = {
|
||||
"react-core": new Set([
|
||||
"react",
|
||||
"react-dom",
|
||||
"react-router",
|
||||
"@remix-run/router",
|
||||
"scheduler",
|
||||
"loose-envify",
|
||||
"object-assign",
|
||||
"use-sync-external-store",
|
||||
"use-sync-external-store/shim",
|
||||
]),
|
||||
"react-ui": new Set([
|
||||
"react-transition-group",
|
||||
"react-error-boundary",
|
||||
"react-hook-form",
|
||||
"react-markdown",
|
||||
"react-virtuoso",
|
||||
]),
|
||||
utils: new Set([
|
||||
"axios",
|
||||
"lodash-es",
|
||||
"dayjs",
|
||||
"js-base64",
|
||||
"js-yaml",
|
||||
"cli-color",
|
||||
"nanoid",
|
||||
]),
|
||||
};
|
||||
|
||||
const NAMESPACE_CHUNK_PREFIXES: Array<{ name: string; prefixes: string[] }> = [
|
||||
{ name: "mui", prefixes: ["@mui/"] },
|
||||
{ name: "tauri-plugins", prefixes: ["@tauri-apps/"] },
|
||||
];
|
||||
|
||||
const LARGE_VENDOR_MATCHERS = [
|
||||
"@emotion/react",
|
||||
"@emotion/styled",
|
||||
"@emotion/cache",
|
||||
"lodash",
|
||||
"monaco",
|
||||
"@dnd-kit",
|
||||
"i18next",
|
||||
];
|
||||
|
||||
const packageSetRules: ChunkRule[] = Object.entries(CHUNK_PACKAGE_SETS).map(
|
||||
([name, pkgSet]) => ({
|
||||
name,
|
||||
match: ({ pkg }) => !!pkg && pkgSet.has(pkg),
|
||||
}),
|
||||
);
|
||||
|
||||
const namespaceRules: ChunkRule[] = NAMESPACE_CHUNK_PREFIXES.map(
|
||||
({ name, prefixes }) => ({
|
||||
name,
|
||||
match: ({ pkg }) =>
|
||||
!!pkg && prefixes.some((prefix) => pkg.startsWith(prefix)),
|
||||
}),
|
||||
);
|
||||
|
||||
const chunkRules: ChunkRule[] = [
|
||||
{ name: "monaco-editor", match: ({ id }) => id.includes("monaco-editor") },
|
||||
...packageSetRules,
|
||||
...namespaceRules,
|
||||
{
|
||||
name: (pkg) => `vendor-${normalizePackageName(pkg ?? "vendor")}`,
|
||||
match: ({ pkg }) =>
|
||||
!!pkg && LARGE_VENDOR_MATCHERS.some((keyword) => pkg.includes(keyword)),
|
||||
},
|
||||
];
|
||||
export default defineConfig({
|
||||
root: "src",
|
||||
server: { port: 3000 },
|
||||
@@ -154,12 +12,10 @@ export default defineConfig({
|
||||
svgr(),
|
||||
react(),
|
||||
legacy({
|
||||
targets: ["edge>=109", "safari>=13"],
|
||||
modernTargets: ["edge>=109", "safari>=14"],
|
||||
renderLegacyChunks: false,
|
||||
modernPolyfills: true,
|
||||
modernPolyfills: ["es.object.has-own", "web.structured-clone"],
|
||||
additionalModernPolyfills: [
|
||||
"core-js/modules/es.object.has-own.js",
|
||||
"core-js/modules/web.structured-clone.js",
|
||||
path.resolve("./src/polyfills/matchMedia.js"),
|
||||
path.resolve("./src/polyfills/WeakRef.js"),
|
||||
path.resolve("./src/polyfills/RegExp.js"),
|
||||
@@ -169,60 +25,7 @@ export default defineConfig({
|
||||
build: {
|
||||
outDir: "../dist",
|
||||
emptyOutDir: true,
|
||||
minify: "terser",
|
||||
chunkSizeWarningLimit: 4500,
|
||||
reportCompressedSize: false,
|
||||
sourcemap: false,
|
||||
cssCodeSplit: true,
|
||||
cssMinify: true,
|
||||
terserOptions: {
|
||||
compress: {
|
||||
drop_console: false,
|
||||
drop_debugger: true,
|
||||
pure_funcs: ["console.debug", "console.trace"],
|
||||
dead_code: true,
|
||||
unused: true,
|
||||
},
|
||||
mangle: {
|
||||
safari10: true,
|
||||
},
|
||||
},
|
||||
rollupOptions: {
|
||||
treeshake: {
|
||||
preset: "recommended",
|
||||
moduleSideEffects: (id) => !id.endsWith(".css"),
|
||||
tryCatchDeoptimization: false,
|
||||
},
|
||||
output: {
|
||||
compact: true,
|
||||
dynamicImportInCjs: true,
|
||||
entryFileNames: (chunkInfo) => {
|
||||
const semanticName = getSemanticNameFromChunk(chunkInfo);
|
||||
|
||||
return `assets/${semanticName}-[hash].js`;
|
||||
},
|
||||
chunkFileNames: (chunkInfo) => {
|
||||
const semanticName = getSemanticNameFromChunk(chunkInfo);
|
||||
|
||||
return `assets/${semanticName}-[hash].js`;
|
||||
},
|
||||
manualChunks(id) {
|
||||
if (!id.includes("node_modules")) return;
|
||||
|
||||
const pkg = getPackageName(id);
|
||||
const ctx: ChunkMatchContext = { id, pkg };
|
||||
for (const rule of chunkRules) {
|
||||
if (rule.match(ctx)) {
|
||||
return typeof rule.name === "function"
|
||||
? rule.name(pkg ?? "vendor")
|
||||
: rule.name;
|
||||
}
|
||||
}
|
||||
|
||||
return "vendor";
|
||||
},
|
||||
},
|
||||
},
|
||||
chunkSizeWarningLimit: 4000,
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
|
||||
Reference in New Issue
Block a user