153 lines
4.7 KiB
JavaScript
153 lines
4.7 KiB
JavaScript
import { defineConfig, loadEnv } from 'vite';
|
|
import react from '@vitejs/plugin-react';
|
|
import path from 'node:path';
|
|
|
|
const projectRoot = import.meta.dirname;
|
|
const outDir = path.resolve(projectRoot, 'dist');
|
|
|
|
function normalizeBasePath(value) {
|
|
const trimmed = String(value || '/').trim();
|
|
const withLeadingSlash = trimmed.startsWith('/') ? trimmed : `/${trimmed}`;
|
|
return withLeadingSlash.endsWith('/') ? withLeadingSlash : `${withLeadingSlash}/`;
|
|
}
|
|
|
|
function rewritePageRequest(request, basePath) {
|
|
if (request.method !== 'GET' || !request.url) return;
|
|
|
|
const [pathname, query = ''] = request.url.split('?');
|
|
const suffix = query ? `?${query}` : '';
|
|
const panelPath = `${basePath}panel`.replace(/\/+/g, '/');
|
|
const apiPath = `${panelPath}/api`;
|
|
|
|
if (pathname === basePath || pathname === basePath.slice(0, -1)) {
|
|
request.url = `/login.html${suffix}`;
|
|
return;
|
|
}
|
|
|
|
if (
|
|
pathname !== apiPath &&
|
|
!pathname.startsWith(`${apiPath}/`) &&
|
|
(pathname === panelPath || pathname.startsWith(`${panelPath}/`))
|
|
) {
|
|
request.url = `/index.html${suffix}`;
|
|
}
|
|
}
|
|
|
|
function adminPagesPlugin(basePath) {
|
|
const configure = (server) => {
|
|
server.middlewares.use((request, _response, next) => {
|
|
rewritePageRequest(request, basePath);
|
|
next();
|
|
});
|
|
};
|
|
|
|
return {
|
|
name: 'admin-ui-pages',
|
|
apply: 'serve',
|
|
transformIndexHtml(html) {
|
|
const escaped = basePath.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
const tag = `<script>window.ADMIN_UI_BASE_PATH="${escaped}";</script>`;
|
|
return html.replace('</head>', `${tag}</head>`);
|
|
},
|
|
configureServer: configure,
|
|
configurePreviewServer: configure,
|
|
};
|
|
}
|
|
|
|
function createProxy(backendTarget) {
|
|
if (!backendTarget) return undefined;
|
|
return {
|
|
'^/(?:[^/]+/)?(?:login|logout|getTwoFactorEnable|csrf-token|panel/api)(?:/|$)': {
|
|
target: backendTarget,
|
|
changeOrigin: true,
|
|
},
|
|
};
|
|
}
|
|
|
|
export default defineConfig(({ mode }) => {
|
|
const env = loadEnv(mode, projectRoot, '');
|
|
const basePath = normalizeBasePath(env.VITE_ADMIN_BASE_PATH);
|
|
const backendTarget = env.VITE_BACKEND_TARGET?.trim();
|
|
|
|
return {
|
|
plugins: [react(), adminPagesPlugin(basePath)],
|
|
resolve: {
|
|
alias: {
|
|
'@': path.resolve(projectRoot, 'src'),
|
|
},
|
|
},
|
|
experimental: {
|
|
renderBuiltUrl(filename, { hostType }) {
|
|
if (hostType === 'js') {
|
|
return {
|
|
runtime: `((window.ADMIN_UI_BASE_PATH||'/')+${JSON.stringify(filename)})`,
|
|
};
|
|
}
|
|
return undefined;
|
|
},
|
|
},
|
|
build: {
|
|
outDir,
|
|
emptyOutDir: true,
|
|
sourcemap: env.VITE_SOURCEMAP === 'true',
|
|
target: 'es2020',
|
|
chunkSizeWarningLimit: 1500,
|
|
rollupOptions: {
|
|
input: {
|
|
index: path.resolve(projectRoot, 'index.html'),
|
|
login: path.resolve(projectRoot, 'login.html'),
|
|
},
|
|
output: {
|
|
manualChunks(id) {
|
|
if (!id.includes('node_modules')) return undefined;
|
|
if (id.includes('/node_modules/antd/')) return 'vendor-antd';
|
|
if (id.includes('/@ant-design/icons/') || id.includes('/@ant-design/icons-svg/')) {
|
|
return 'vendor-icons';
|
|
}
|
|
if (
|
|
id.includes('/node_modules/@rc-component/') ||
|
|
id.includes('/node_modules/rc-') ||
|
|
id.includes('/@ant-design/cssinjs') ||
|
|
id.includes('/@ant-design/colors') ||
|
|
id.includes('/@ant-design/fast-color') ||
|
|
id.includes('/@ant-design/react-slick') ||
|
|
id.includes('/@ctrl/tinycolor')
|
|
) {
|
|
return 'vendor-antd';
|
|
}
|
|
if (
|
|
id.includes('/node_modules/react-i18next/') ||
|
|
id.includes('/node_modules/i18next/')
|
|
) {
|
|
return 'vendor-i18next';
|
|
}
|
|
if (
|
|
id.includes('/node_modules/react/') ||
|
|
id.includes('/node_modules/react-dom/') ||
|
|
id.includes('/node_modules/scheduler/')
|
|
) {
|
|
return 'vendor-react';
|
|
}
|
|
if (id.includes('/node_modules/@tanstack/')) return 'vendor-tanstack';
|
|
if (id.includes('/node_modules/react-hook-form/')) return 'vendor-react-hook-form';
|
|
if (id.includes('/node_modules/react-router')) return 'vendor-router';
|
|
if (id.includes('/node_modules/dayjs/')) return 'vendor-dayjs';
|
|
return 'vendor';
|
|
},
|
|
},
|
|
},
|
|
},
|
|
server: {
|
|
host: '0.0.0.0',
|
|
port: 19999,
|
|
strictPort: true,
|
|
proxy: createProxy(backendTarget),
|
|
},
|
|
preview: {
|
|
host: '0.0.0.0',
|
|
port: 19999,
|
|
strictPort: true,
|
|
},
|
|
};
|
|
});
|