mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-10-23 03:27:43 +09:00
Rolldown's manualChunks shim lets a group capture its dependencies, so recharts pulled React core into vendor-charts and @xyflow claimed helpers i18n needs; the entry, Login included, preloaded both chunks. Priority groups give React first claim and keep charts/flow to their own package. Entry preload: 2.41 MB -> 1.85 MB (726 -> 573 KB gz).
140 lines
6.7 KiB
JavaScript
140 lines
6.7 KiB
JavaScript
/* global process */
|
|
import { defineConfig, loadEnv } from 'vite'
|
|
import react from '@vitejs/plugin-react'
|
|
import { fileURLToPath } from 'url'
|
|
import { VENDOR_IMPORTMAP } from './src/plugins/runtime/vendorManifest.js'
|
|
|
|
// Runtime-extension import map (plan 25 Decision 2). A runtime-loaded extension
|
|
// bundle externalizes exactly these bare specifiers and resolves them at load
|
|
// time to the panel's own singleton instances via the `/serverkit-vendor/*.mjs`
|
|
// shims (fed by src/plugins/runtime/vendorShare.js). Injected into index.html at
|
|
// BUILD time only: Vite's dev server does its own bare-specifier resolution, and
|
|
// runtime loading is a production concern (dev uses the build-time glob path).
|
|
// The map is inert for the host's own code (bundled to hashed relative chunks,
|
|
// never bare specifiers) — it only affects the extension blobs.
|
|
// Sourced from the ONE vendor manifest, so the import map, the shims under
|
|
// public/serverkit-vendor/ and vendorShare's namespace capture cannot drift
|
|
// apart. They previously did: two mapped specifiers had no shim at all.
|
|
|
|
function serverkitImportmap() {
|
|
return {
|
|
name: 'serverkit-vendor-importmap',
|
|
apply: 'build',
|
|
transformIndexHtml() {
|
|
return [{
|
|
tag: 'script',
|
|
attrs: { type: 'importmap' },
|
|
children: JSON.stringify(VENDOR_IMPORTMAP),
|
|
injectTo: 'head-prepend',
|
|
}]
|
|
},
|
|
}
|
|
}
|
|
|
|
export default defineConfig(({ mode }) => {
|
|
const env = loadEnv(mode, process.cwd(), '')
|
|
const frontendPort = Number(env.SERVERKIT_FRONTEND_PORT) || 41921
|
|
const apiTarget = (env.VITE_API_URL || 'http://localhost:47927/api/v1').replace(/\/api\/v1\/?$/, '')
|
|
|
|
const rawAllowedHosts = (env.VITE_ALLOWED_HOSTS || '').trim()
|
|
let allowedHosts
|
|
if (rawAllowedHosts === 'all') {
|
|
allowedHosts = true
|
|
} else if (rawAllowedHosts) {
|
|
allowedHosts = rawAllowedHosts.split(',').map(s => s.trim()).filter(Boolean)
|
|
}
|
|
|
|
return {
|
|
plugins: [react(), serverkitImportmap()],
|
|
resolve: {
|
|
alias: {
|
|
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
|
// Stable import path for plugin code:
|
|
// import { api, useAuth } from 'serverkit-sdk';
|
|
// Internal restructures of src/plugins/sdk are invisible
|
|
// to plugins as long as the named exports stay stable.
|
|
'serverkit-sdk': fileURLToPath(new URL('./src/plugins/sdk/index.js', import.meta.url)),
|
|
},
|
|
// Force every `react` / `react-dom` / `react-router-dom`
|
|
// import (host code AND plugin code loaded via
|
|
// import.meta.glob) to resolve to one copy. Without this
|
|
// Vite can hand plugins a different React instance if dep
|
|
// optimization runs mid-session, producing the
|
|
// "Invalid hook call / ReactCurrentDispatcher is null"
|
|
// crash inside the contributions hook.
|
|
//
|
|
// Do NOT add resolve.alias entries for these — aliasing to
|
|
// the package directory bypasses Vite's optimizeDeps and
|
|
// serves raw ESM, which (combined with pre-bundled
|
|
// react-dom) recreates the same two-copies problem from the
|
|
// other direction.
|
|
// i18next/react-i18next join the list for the same reason: two
|
|
// instances means an extension's t() reads an uninitialised store
|
|
// and silently renders English forever (plan 79).
|
|
dedupe: ['react', 'react-dom', 'react-router-dom', 'i18next', 'react-i18next'],
|
|
},
|
|
optimizeDeps: {
|
|
// Pre-bundle the renderer at server start instead of
|
|
// discovering it lazily. Lazy discovery is what triggers the
|
|
// mid-session re-bundle that strands the open browser tab
|
|
// on a stale React URL.
|
|
include: ['react', 'react-dom', 'react-router-dom', 'i18next', 'react-i18next'],
|
|
},
|
|
server: {
|
|
port: frontendPort,
|
|
...(allowedHosts !== undefined ? { allowedHosts } : {}),
|
|
proxy: {
|
|
'/api': {
|
|
target: apiTarget,
|
|
changeOrigin: true,
|
|
},
|
|
'/socket.io': {
|
|
target: apiTarget,
|
|
changeOrigin: true,
|
|
ws: true,
|
|
},
|
|
},
|
|
// Enable polling for WSL (Windows filesystem doesn't support inotify)
|
|
watch: {
|
|
usePolling: true,
|
|
interval: 1000,
|
|
},
|
|
},
|
|
css: {
|
|
preprocessorOptions: {
|
|
scss: {
|
|
// Silence Dart Sass deprecation warnings for @import and slash-div
|
|
// These are expected during migration from LESS and will be addressed
|
|
// when moving to @use/@forward module system
|
|
silenceDeprecations: ['import', 'slash-div', 'legacy-js-api', 'global-builtin', 'color-functions', 'strict-unary'],
|
|
},
|
|
},
|
|
},
|
|
build: {
|
|
sourcemap: false,
|
|
rollupOptions: {
|
|
output: {
|
|
// A group also captures its matched modules' dependencies,
|
|
// so priority decides who claims a shared one. React must
|
|
// win: with manualChunks, recharts pulled React core into
|
|
// vendor-charts and every page (Login included) preloaded
|
|
// the chart and flow libraries. Unmatched modules fall
|
|
// through to the default chunking.
|
|
codeSplitting: {
|
|
groups: [
|
|
{ name: 'vendor-react', priority: 50, test: /[\\/]node_modules[\\/](react|react-dom|react-router|react-router-dom|@remix-run[\\/]router|scheduler)[\\/]/ },
|
|
{ name: 'vendor-icons', priority: 40, test: /[\\/]node_modules[\\/]lucide-react[\\/]/ },
|
|
{ name: 'vendor-xterm', priority: 30, test: /[\\/]node_modules[\\/]@xterm[\\/]/ },
|
|
// Only the package itself: their small shared deps
|
|
// are also used by i18n, which would otherwise
|
|
// import (and preload) the whole chunk for them.
|
|
{ name: 'vendor-flow', priority: 20, includeDependenciesRecursively: false, test: /[\\/]node_modules[\\/]@xyflow[\\/]/ },
|
|
{ name: 'vendor-charts', priority: 10, includeDependenciesRecursively: false, test: /[\\/]node_modules[\\/]recharts[\\/]/ },
|
|
],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
})
|