Files
creator-hub/web/vite.config.ts
T

110 lines
3.8 KiB
TypeScript

import http from 'node:http'
import https from 'node:https'
import tailwindcss from '@tailwindcss/vite'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import viteReact from '@vitejs/plugin-react'
import { defineConfig, type Plugin } from 'vite'
import tsconfigPaths from 'vite-tsconfig-paths'
import { nitro } from 'nitro/vite'
const flattenPlugins = (plugins: Array<unknown>): Plugin[] =>
plugins.flat(Infinity).filter((plugin): plugin is Plugin => Boolean(plugin))
type BuildWarning = { code?: string; id?: string; message: string }
function warnBuild(warning: BuildWarning, warn: (warning: BuildWarning) => void) {
const dependency = warning.id?.includes('/node_modules/') ?? false
const knownDependencyNoise = (
(dependency && warning.code === 'MODULE_LEVEL_DIRECTIVE' && warning.message.includes('use client'))
|| (warning.code === 'UNUSED_EXTERNAL_IMPORT' && warning.message.includes('@tanstack/'))
)
if (!knownDependencyNoise) warn(warning)
}
const rollupWarningOptions = { onwarn: warnBuild }
function creatorHubBuildWarningPlugin(): Plugin {
return {
name: 'creatorhub:build-warning-filter',
config() {
return {
environments: {
ssr: { build: { rollupOptions: rollupWarningOptions } },
},
}
},
}
}
function creatorHubAssetFetchDest(): Plugin {
return {
name: 'creatorhub:asset-fetch-dest',
enforce: 'pre',
configureServer(server) {
server.middlewares.use((request, _response, next) => {
// Chromium can omit Fetch Metadata for LAN requests; Nitro otherwise treats these assets as document routes.
if (request.headers['sec-fetch-dest']) return next()
const pathname = request.url?.split(/[?#]/, 1)[0] ?? ''
if (/\.css$/.test(pathname)) request.headers['sec-fetch-dest'] = 'style'
else if (/\.(?:[cm]?[jt]sx?|mjs)$/.test(pathname)) request.headers['sec-fetch-dest'] = 'script'
next()
})
}
}
}
function creatorHubApiProxy(): Plugin {
const target = process.env.CREATORHUB_CONTROL_PLANE_URL ?? 'http://127.0.0.1:8082'
return {
name: 'creatorhub:control-plane-proxy',
configureServer(server) {
server.middlewares.use((request, response, next) => {
if (!request.url?.startsWith('/api/')) return next()
const upstreamURL = new URL(request.url, target)
const transport = upstreamURL.protocol === 'https:' ? https : http
const headers = { ...request.headers, host: upstreamURL.host }
const upstream = transport.request(upstreamURL, { method: request.method, headers }, (upstreamResponse) => {
response.statusCode = upstreamResponse.statusCode ?? 502
for (const [name, value] of Object.entries(upstreamResponse.headers)) {
if (value !== undefined) response.setHeader(name, value)
}
upstreamResponse.pipe(response)
})
upstream.on('error', (error) => {
server.config.logger.error(`[creatorhub:control-plane-proxy] ${request.method ?? 'GET'} ${request.url}: ${error.message}`)
if (!response.headersSent) {
response.statusCode = 502
response.setHeader('content-type', 'application/json')
response.end(JSON.stringify({ error: '控制面代理不可用' }))
} else {
response.destroy(error)
}
})
request.pipe(upstream)
})
},
}
}
export default defineConfig({
server: {
host: true,
port: 5100,
strictPort: true,
proxy: { '/api': 'http://127.0.0.1:8082' }
},
build: {
rollupOptions: rollupWarningOptions
},
plugins: flattenPlugins([
creatorHubAssetFetchDest(),
creatorHubApiProxy(),
tsconfigPaths(),
tailwindcss(),
tanstackStart(),
creatorHubBuildWarningPlugin(),
nitro({ preset: process.env.SERVER_PRESET, rollupConfig: rollupWarningOptions }),
viteReact()
])
})