Files
Genarrative/vite.config.ts
T
kdletters f3ab2f2ec0 恢复平台账号顶栏与我的页签
按新版创作页原布局恢复泥点入口与账号身份胶囊。

在桌面侧栏补回我的页签及游客、登录态个人页面。

个人页面只复用账号、钱包、统计、设置和法律信息等平台能力。

补充壳层与个人页面回归测试并更新退役边界文档。
2026-07-18 16:15:40 +08:00

330 lines
10 KiB
TypeScript

import { rmSync } from 'node:fs';
import path from 'node:path';
import tailwindcss from '@tailwindcss/vite';
import react from '@vitejs/plugin-react';
import postcss from 'postcss';
import { defineConfig, loadEnv, type Plugin } from 'vite';
const RETIRED_TEMPLATE_CSS_PATTERN =
/(?:baby-object|bark-battle|big-fish|child-motion|creation-(?:agent|work)|creative-agent|custom-world|jump-hop|match3d|platform-recommend|platform-work-detail|public-work|puzzle|rpg|square-hole|unified-creation|visual-novel|wooden-fish)/iu;
const ACTIVE_TAILWIND_SOURCES = `@import 'tailwindcss' source(none);
@source "./active-main.tsx";
@source "./ActiveApp.tsx";
@source "./AuthenticatedApp.tsx";
@source "./components/auth";
@source "./components/common";
@source "./components/creation-home";
@source "./components/image-editor";
@source "./components/project";
@source "./components/platform-entry/PlatformEntryFlowShell.tsx";
@source "./components/platform-entry/PlatformEntryActiveFlowShell.tsx";
@source "./components/platform-entry/PlatformActiveProfileView.tsx";
@source "./components/platform-entry/PlatformProfilePrimitives.tsx";
@source "./components/platform-entry/PlatformProfileModalShell.tsx";
@source "./components/platform-entry/PlatformProfileRechargeModal.tsx";
@source "./components/platform-entry/PlatformProfileWalletLedgerModal.tsx";
@source "./components/platform-entry/PlatformRechargePaymentStatusDialogs.tsx";
@source "./editor";
@source "../packages/shared/src/components";`;
const RETIRED_PUBLIC_ASSET_PATHS = [
'/branding/jump-hop-taonier-character.png',
'/branding/mobile-home-welcome-taonier-ip.png',
'/anthro-cat-illustrations',
'/bark-battle-assets',
'/character',
'/child-motion-demo',
'/creation-type-references',
'/edutainment-baby-object',
'/generated-character-drafts',
'/generated-characters',
'/generated-qwen-sprites',
'/Icons',
'/creation-type-references/jump-hop.webp',
'/creation-type-references/match3d.webp',
'/match3d-background-references',
'/match3d-style-references',
'/Pixel Monsters Vol1',
'/puzzle-creation-templates',
'/scene_bg',
'/UI',
'/ui-previews',
'/visual-novel-style-references',
'/wooden-fish',
] as const;
function isRetiredPublicAssetPath(pathname: string) {
return RETIRED_PUBLIC_ASSET_PATHS.some(
(prefix) => pathname === prefix || pathname.startsWith(`${prefix}/`),
);
}
function retiredCreationTemplateAssetsPlugin(): Plugin {
return {
name: 'retired-creation-template-assets',
configureServer(server) {
server.middlewares.use((request, response, next) => {
const pathname = new URL(request.url ?? '/', 'http://localhost')
.pathname;
if (!isRetiredPublicAssetPath(pathname)) {
next();
return;
}
response.statusCode = 404;
response.end();
});
},
writeBundle(options) {
const outputDir = path.resolve(__dirname, options.dir ?? 'dist');
for (const assetPath of RETIRED_PUBLIC_ASSET_PATHS) {
rmSync(path.join(outputDir, assetPath.slice(1)), {
force: true,
recursive: true,
});
}
},
};
}
function retiredCreationTemplateCssPlugin(): Plugin {
const stripRetiredCss = (code: string, from: string) => {
const root = postcss.parse(code, { from });
root.walkRules((rule) => {
if (RETIRED_TEMPLATE_CSS_PATTERN.test(rule.selector)) {
rule.remove();
}
});
root.walkAtRules((atRule) => {
if (
(atRule.name === 'keyframes' || atRule.name === 'source') &&
RETIRED_TEMPLATE_CSS_PATTERN.test(atRule.params)
) {
atRule.remove();
}
});
root.walkDecls((declaration) => {
if (
RETIRED_TEMPLATE_CSS_PATTERN.test(declaration.prop) ||
RETIRED_TEMPLATE_CSS_PATTERN.test(declaration.value)
) {
declaration.remove();
}
});
return root.toString();
};
return {
name: 'retired-creation-template-css',
enforce: 'pre',
transform(code, id) {
if (
!id.endsWith('/src/index.css') &&
!id.endsWith('/packages/shared/src/theme.css')
) {
return null;
}
const activeSourceCode = id.endsWith('/src/index.css')
? code.replace("@import 'tailwindcss';", ACTIVE_TAILWIND_SOURCES)
: code;
return { code: stripRetiredCss(activeSourceCode, id), map: null };
},
generateBundle(_options, bundle) {
Object.values(bundle).forEach((entry) => {
if (entry.type !== 'asset' || !entry.fileName.endsWith('.css')) {
return;
}
entry.source = stripRetiredCss(
typeof entry.source === 'string'
? entry.source
: new TextDecoder().decode(entry.source),
entry.fileName,
);
});
},
};
}
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, __dirname, '');
const ignoredWatchGlobs = [
// Prevent a root-level nohup log from triggering a Vite reload loop.
'**/nohup.out',
'**/.git/**',
'**/.worktrees/**',
'**/dist/**',
'**/dist_check/**',
'**/dist_check_final/**',
'**/dist_check_monster_position/**',
'**/temp*build*/**',
'**/public/generated-character-drafts/**',
'**/public/generated-characters/**',
'**/public/generated-custom-world-scenes/**',
'**/public/generated-qwen-sprites/**',
'**/public/child-motion-demo/**',
'**/public/anthro-cat-illustrations/**',
'**/public/bark-battle-assets/**',
'**/public/character/**',
'**/public/creation-type-references/**',
'**/public/edutainment-baby-object/**',
'**/public/match3d-background-references/**',
'**/public/match3d-style-references/**',
'**/public/puzzle-creation-templates/**',
'**/public/visual-novel-style-references/**',
'**/public/wooden-fish/**',
'**/src/components/child-motion-demo/**',
'**/src/components/asset-studio/**',
'**/src/components/bark-battle-creation/**',
'**/src/components/big-fish-*/**',
'**/src/components/creation-agent/**',
'**/src/components/creative-agent/**',
'**/src/components/custom-world-*/**',
'**/src/components/edutainment-*/**',
'**/src/ChildMotionDemoApp.tsx',
'**/src/Match3DPlaygroundApp.tsx',
'**/src/components/jump-hop-result/**',
'**/src/components/jump-hop-runtime/**',
'**/src/components/match3d-result/**',
'**/src/components/match3d-runtime/**',
'**/src/components/puzzle-*/**',
'**/src/components/rpg-creation-*/**',
'**/src/components/rpg-runtime-*/**',
'**/src/components/square-hole-*/**',
'**/src/components/unified-creation/**',
'**/src/components/visual-novel-*/**',
'**/src/components/wooden-fish-*/**',
'**/src/components/platform-entry/platformMatch3DRuntimeProfile*',
'**/src/components/unified-creation/workspaces/JumpHopCreationWorkspace*',
'**/src/components/unified-creation/workspaces/Match3DCreationWorkspace*',
'**/src/services/child-motion-demo/**',
'**/src/services/bark-battle-*/**',
'**/src/services/big-fish-*/**',
'**/src/services/creation-*/**',
'**/src/services/creative-agent/**',
'**/src/services/edutainment-*/**',
'**/src/services/jump-hop/**',
'**/src/services/match3d-creation/**',
'**/src/services/match3d-runtime/**',
'**/src/services/match3d-works/**',
'**/src/services/match3dGeneratedModelCache*',
'**/src/services/match3dSpritesheetParser*',
'**/src/services/puzzle-*/**',
'**/src/services/rpg-creation/**',
'**/src/services/square-hole-*/**',
'**/src/services/visual-novel-*/**',
'**/src/services/wooden-fish/**',
'**/backend-rewrite-tasklist/**',
'**/docs/**',
'**/jenkins/**',
'**/media/**',
'**/scripts/**',
'**/server-rs/**',
'**/server-rs/target/**',
'**/*.test.ts',
'**/*.test.tsx',
'**/*.spec.ts',
'**/*.spec.tsx',
];
const rustServerTarget =
env.RUST_SERVER_TARGET ||
env.GENARRATIVE_API_TARGET ||
`http://127.0.0.1:${env.GENARRATIVE_API_PORT || '3100'}`;
const runtimeServerTarget =
env.GENARRATIVE_RUNTIME_SERVER_TARGET || rustServerTarget;
const adminWebTarget =
env.ADMIN_WEB_TARGET || `http://127.0.0.1:${env.ADMIN_WEB_PORT || '3102'}`;
return {
root: __dirname,
envDir: __dirname,
plugins: [
retiredCreationTemplateCssPlugin(),
react(),
tailwindcss(),
retiredCreationTemplateAssetsPlugin(),
],
define: {
'process.env.GEMINI_API_KEY': JSON.stringify(env.GEMINI_API_KEY),
},
resolve: {
alias: {
'@': path.resolve(__dirname, '.'),
},
},
optimizeDeps: {
// Only crawl the real app entry so temporary build folders do not get
// treated as extra HTML entrypoints during dependency scanning.
entries: ['index.html'],
},
build: {
chunkSizeWarningLimit: 1000,
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('/node_modules/motion')) {
return 'motion-vendor';
}
if (id.includes('/src/services/')) {
return 'app-services';
}
},
},
},
},
server: {
allowedHosts: ['outfield-outlook-reprocess.ngrok-free.dev'],
// HMR is disabled in AI Studio via DISABLE_HMR env var.
// Do not modify; file watching is disabled to prevent flickering during agent edits.
hmr: process.env.DISABLE_HMR !== 'true',
proxy: {
'/admin/': {
target: adminWebTarget,
changeOrigin: true,
secure: false,
},
'/api/auth': {
target: runtimeServerTarget,
changeOrigin: true,
secure: false,
},
'/api/profile': {
target: runtimeServerTarget,
changeOrigin: true,
secure: false,
},
'/api/runtime': {
target: runtimeServerTarget,
changeOrigin: true,
secure: false,
},
'/api/editor': {
target: runtimeServerTarget,
changeOrigin: true,
secure: false,
},
'/api/assets': {
target: runtimeServerTarget,
changeOrigin: true,
secure: false,
},
'/api/llm': {
target: runtimeServerTarget,
changeOrigin: true,
secure: false,
},
'/api/ws': {
target: runtimeServerTarget,
changeOrigin: true,
secure: false,
ws: true,
},
},
watch: {
ignored: ignoredWatchGlobs,
},
},
};
});