Include xll-miniapp prototype, PRD resources, annotation directory sync, agent skills, and cloud publishing setup. Co-authored-by: Cursor <cursoragent@cursor.com>
225 lines
6.7 KiB
TypeScript
225 lines
6.7 KiB
TypeScript
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import { defineConfig } from 'vite';
|
|
import react from '@vitejs/plugin-react';
|
|
import tailwindcss from '@tailwindcss/vite';
|
|
|
|
import { forceInlineDynamicImportsOff } from './vite-plugins/forceInlineDynamicImportsOff';
|
|
import { injectStablePageIds } from './vite-plugins/injectStablePageIds';
|
|
import { clientPreviewPlugin } from './vite-plugins/clientPreviewPlugin';
|
|
import { autoStartMakeServerPlugin } from './vite-plugins/autoStartMakeServerPlugin';
|
|
import { writeDevServerInfoPlugin } from './vite-plugins/writeDevServerInfoPlugin';
|
|
import { axhubComponentEnforcer } from './vite-plugins/axhubComponentEnforcer';
|
|
import { websocketPlugin } from './vite-plugins/websocketPlugin';
|
|
import { canvasHotUpdateFilterPlugin } from './vite-plugins/canvasHotUpdateFilter';
|
|
import {
|
|
MAKE_CONFIG_RELATIVE_PATH,
|
|
MAKE_ENTRIES_RELATIVE_PATH,
|
|
} from './vite-plugins/utils/makeConstants';
|
|
import {
|
|
readEntriesManifest,
|
|
scanProjectEntries,
|
|
writeEntriesManifestAtomic,
|
|
} from './vite-plugins/utils/entriesManifest';
|
|
|
|
const projectRoot = process.cwd();
|
|
const OFFICIAL_CLIENT_DEV_PORT = 51720;
|
|
|
|
/** Read allowLAN from the shared make config to align with make-server. */
|
|
function readAllowLAN(): boolean {
|
|
try {
|
|
const configPath = path.resolve(projectRoot, MAKE_CONFIG_RELATIVE_PATH);
|
|
if (fs.existsSync(configPath)) {
|
|
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
return config?.server?.allowLAN !== false;
|
|
}
|
|
} catch {
|
|
// Fall through to default.
|
|
}
|
|
return true;
|
|
}
|
|
|
|
writeEntriesManifestAtomic(
|
|
projectRoot,
|
|
scanProjectEntries(projectRoot, ['prototypes', 'themes']),
|
|
);
|
|
const entries = readEntriesManifest(projectRoot);
|
|
|
|
const entryKey = process.env.ENTRY_KEY;
|
|
const jsEntries = entries.js as Record<string, string>;
|
|
const htmlEntries = entries.html as Record<string, string>;
|
|
|
|
const hasSingleEntry = typeof entryKey === 'string' && entryKey.length > 0;
|
|
let rollupInput: Record<string, string> = htmlEntries;
|
|
|
|
if (hasSingleEntry) {
|
|
if (!jsEntries[entryKey as string]) {
|
|
throw new Error(`ENTRY_KEY=${entryKey} was not found in ${MAKE_ENTRIES_RELATIVE_PATH}.`);
|
|
}
|
|
rollupInput = { [entryKey as string]: jsEntries[entryKey as string] };
|
|
}
|
|
|
|
const isIifeBuild = hasSingleEntry;
|
|
const devServerWatchIgnored = [
|
|
'**/.axhub/make/**',
|
|
'**/canvas-assets/**',
|
|
'**/.spec/**',
|
|
'**/*.excalidraw',
|
|
];
|
|
|
|
export default defineConfig(({ command }) => {
|
|
const isServe = command === 'serve';
|
|
|
|
const config: any = {
|
|
plugins: [
|
|
tailwindcss(),
|
|
isServe ? canvasHotUpdateFilterPlugin() : null,
|
|
injectStablePageIds(),
|
|
isServe ? writeDevServerInfoPlugin() : null,
|
|
isServe ? autoStartMakeServerPlugin() : null,
|
|
isServe ? websocketPlugin() : null,
|
|
isServe ? clientPreviewPlugin() : null,
|
|
forceInlineDynamicImportsOff(isIifeBuild),
|
|
isIifeBuild ? axhubComponentEnforcer(jsEntries[entryKey as string]) : null,
|
|
react({
|
|
jsxRuntime: 'classic',
|
|
babel: { configFile: false, babelrc: false },
|
|
}),
|
|
].filter(Boolean) as Plugin[],
|
|
|
|
root: 'src',
|
|
publicDir: false,
|
|
|
|
optimizeDeps: {
|
|
include: [
|
|
'echarts',
|
|
'lucide-react',
|
|
],
|
|
},
|
|
|
|
resolve: {
|
|
dedupe: [
|
|
'react',
|
|
'react-dom',
|
|
'react/jsx-runtime',
|
|
'react/jsx-dev-runtime',
|
|
],
|
|
alias: [
|
|
{ find: '@', replacement: path.resolve(projectRoot, 'src') },
|
|
!isIifeBuild && !isServe && fs.existsSync(path.resolve(projectRoot, 'src/common/react-shim.js')) && {
|
|
find: /^react$/,
|
|
replacement: path.resolve(projectRoot, 'src/common/react-shim.js'),
|
|
},
|
|
!isIifeBuild && !isServe && fs.existsSync(path.resolve(projectRoot, 'src/common/react-dom-shim.js')) && {
|
|
find: /^react-dom$/,
|
|
replacement: path.resolve(projectRoot, 'src/common/react-dom-shim.js'),
|
|
},
|
|
].filter(Boolean) as { find: string | RegExp; replacement: string }[],
|
|
},
|
|
|
|
css: {
|
|
preprocessorOptions: {
|
|
scss: { api: 'modern-compiler' },
|
|
sass: { api: 'modern-compiler' },
|
|
},
|
|
},
|
|
|
|
server: {
|
|
port: OFFICIAL_CLIENT_DEV_PORT,
|
|
strictPort: false,
|
|
host: readAllowLAN() ? '0.0.0.0' : 'localhost',
|
|
open: false,
|
|
cors: true,
|
|
hmr: { overlay: false },
|
|
watch: {
|
|
ignored: devServerWatchIgnored,
|
|
},
|
|
headers: {
|
|
'Access-Control-Allow-Origin': '*',
|
|
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
|
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
|
},
|
|
},
|
|
|
|
build: {
|
|
outDir: path.resolve(projectRoot, 'dist'),
|
|
emptyOutDir: !isIifeBuild,
|
|
target: isIifeBuild ? 'es2015' : 'esnext',
|
|
assetsInlineLimit: 1024 * 1024,
|
|
rollupOptions: {
|
|
input: rollupInput,
|
|
external: isIifeBuild ? ['react', 'react-dom'] : [],
|
|
output: {
|
|
entryFileNames: (chunkInfo: { name: string }) => `${chunkInfo.name}.js`,
|
|
format: isIifeBuild ? 'iife' : 'es',
|
|
name: 'UserComponent',
|
|
...(isIifeBuild
|
|
? {
|
|
globals: {
|
|
react: 'React',
|
|
'react-dom': 'ReactDOM',
|
|
},
|
|
generatedCode: { constBindings: false },
|
|
}
|
|
: {}),
|
|
},
|
|
},
|
|
minify: isIifeBuild ? 'esbuild' : false,
|
|
},
|
|
|
|
esbuild: isIifeBuild
|
|
? {
|
|
target: 'es2015',
|
|
legalComments: 'none',
|
|
keepNames: true,
|
|
}
|
|
: {
|
|
jsx: 'transform',
|
|
jsxFactory: 'React.createElement',
|
|
jsxFragment: 'React.Fragment',
|
|
},
|
|
|
|
test: {
|
|
globals: true,
|
|
environment: 'node',
|
|
include: [
|
|
'tests/**/*.test.ts',
|
|
'tests/**/*.test.tsx',
|
|
'scripts/**/*.test.ts',
|
|
'scripts/**/*.test.mjs',
|
|
'vite-plugins/**/*.test.ts',
|
|
],
|
|
root: '.',
|
|
coverage: {
|
|
provider: 'v8',
|
|
reporter: ['text', 'text-summary', 'json-summary', 'html'],
|
|
reportOnFailure: true,
|
|
include: [
|
|
'src/common/useHashPage.ts',
|
|
'src/common/side-menu/side-menu-utils.ts',
|
|
'scripts/sync-project-metadata.mjs',
|
|
'vite-plugins/**/*.{ts,js}',
|
|
],
|
|
exclude: [
|
|
'**/*.d.ts',
|
|
'**/*.test.*',
|
|
'src/prototypes/**',
|
|
'src/themes/**',
|
|
'src/common/DesignMdBatchShowcase/**',
|
|
'src/common/ThemeShell/**',
|
|
'src/common/VariantSwitcher.tsx',
|
|
'src/common/axure-types.ts',
|
|
'src/common/config-panel-types.ts',
|
|
'src/common/react-shim.js',
|
|
'src/common/react-dom-shim.js',
|
|
'**/templates/**',
|
|
'**/dist/**',
|
|
'**/node_modules/**',
|
|
],
|
|
},
|
|
},
|
|
};
|
|
|
|
return config;
|
|
});
|