Skip to content

Commit e97a4d8

Browse files
committed
feat: add serverRoutes option to override exclude patterns
Routes matching serverRoutes patterns will be handled by the server even if they match exclude patterns (e.g., URLs ending in .jpg). Example: srvx({ serverRoutes: ['/api/*'] }) This allows API routes like /api/uploads/image.jpg to be handled by the server instead of being skipped due to the .jpg extension.
1 parent 05b898a commit e97a4d8

File tree

2 files changed

+38
-5
lines changed

2 files changed

+38
-5
lines changed

src/dev-server.ts

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import type { Plugin, ViteDevServer } from "vite";
66
export interface DevServerOptions {
77
entry?: string;
88
exclude?: (string | RegExp)[];
9+
/** Routes that should always be handled by the server, even if they match exclude patterns */
10+
serverRoutes?: (string | RegExp)[];
911
injectClientScript?: boolean;
1012
loadModule?: (server: ViteDevServer, entry: string) => Promise<any>;
1113
}
@@ -62,17 +64,47 @@ function createMiddleware(server: ViteDevServer, options: DevServerOptions) {
6264
}
6365
}
6466

65-
const exclude = options.exclude ?? defaultOptions.exclude ?? [];
67+
// Check if URL matches serverRoutes (these take priority over exclude patterns)
68+
const serverRoutes = options.serverRoutes ?? [];
69+
let isServerRoute = false;
6670

67-
for (const pattern of exclude) {
71+
for (const pattern of serverRoutes) {
6872
if (req.url) {
6973
if (pattern instanceof RegExp) {
7074
if (pattern.test(req.url)) {
71-
return next();
75+
isServerRoute = true;
76+
break;
7277
}
7378
} else if (typeof pattern === "string") {
74-
if (req.url.startsWith(pattern)) {
75-
return next();
79+
// Support glob-style patterns like "/api/*"
80+
if (pattern.endsWith("/*")) {
81+
const prefix = pattern.slice(0, -1); // Remove the "*"
82+
if (req.url.startsWith(prefix) || req.url === prefix.slice(0, -1)) {
83+
isServerRoute = true;
84+
break;
85+
}
86+
} else if (req.url.startsWith(pattern)) {
87+
isServerRoute = true;
88+
break;
89+
}
90+
}
91+
}
92+
}
93+
94+
// Only check exclude patterns if this is not a server route
95+
if (!isServerRoute) {
96+
const exclude = options.exclude ?? defaultOptions.exclude ?? [];
97+
98+
for (const pattern of exclude) {
99+
if (req.url) {
100+
if (pattern instanceof RegExp) {
101+
if (pattern.test(req.url)) {
102+
return next();
103+
}
104+
} else if (typeof pattern === "string") {
105+
if (req.url.startsWith(pattern)) {
106+
return next();
107+
}
76108
}
77109
}
78110
}

src/srvx.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export function srvx(options?: SrvxOptions): Plugin[] {
2828
devServer({
2929
entry: mergedOptions.entry,
3030
exclude: mergedOptions.exclude,
31+
serverRoutes: mergedOptions.serverRoutes,
3132
injectClientScript: mergedOptions.injectClientScript,
3233
loadModule: mergedOptions.loadModule,
3334
}),

0 commit comments

Comments
 (0)