Skip to content

Commit 14db473

Browse files
patak-devbenmccannShinigami92bluwy
authoredJun 18, 2022
feat!: appType (spa, mpa, custom), boolean middlewareMode (#8452)
Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com> Co-authored-by: Shinigami <chrissi92@hotmail.de> Co-authored-by: Bjorn Lu <bjornlu.dev@gmail.com>
1 parent dbd9688 commit 14db473

File tree

13 files changed

+90
-59
lines changed

13 files changed

+90
-59
lines changed
 

‎docs/config/server-options.md

+11-11
Original file line numberDiff line numberDiff line change
@@ -146,14 +146,12 @@ export default defineConfig({
146146

147147
## server.middlewareMode
148148

149-
- **Type:** `'ssr' | 'html'`
150-
151-
Create Vite server in middleware mode. (without a HTTP server)
149+
- **Type:** `boolean`
150+
- **Default:** `false`
152151

153-
- `'ssr'` will disable Vite's own HTML serving logic so that you should serve `index.html` manually.
154-
- `'html'` will enable Vite's own HTML serving logic.
152+
Create Vite server in middleware mode.
155153

156-
- **Related:** [SSR - Setting Up the Dev Server](/guide/ssr#setting-up-the-dev-server)
154+
- **Related:** [appType](./shared-options#apptype), [SSR - Setting Up the Dev Server](/guide/ssr#setting-up-the-dev-server)
157155

158156
- **Example:**
159157

@@ -164,17 +162,19 @@ const { createServer: createViteServer } = require('vite')
164162
async function createServer() {
165163
const app = express()
166164

167-
// Create Vite server in middleware mode.
165+
// Create Vite server in middleware mode
168166
const vite = await createViteServer({
169-
server: { middlewareMode: 'ssr' }
167+
server: { middlewareMode: true },
168+
appType: 'custom' // don't include Vite's default HTML handling middlewares
170169
})
171170
// Use vite's connect instance as middleware
172171
app.use(vite.middlewares)
173172

174173
app.use('*', async (req, res) => {
175-
// If `middlewareMode` is `'ssr'`, should serve `index.html` here.
176-
// If `middlewareMode` is `'html'`, there is no need to serve `index.html`
177-
// because Vite will do that.
174+
// Since `appType` is `'custom'`, should serve response here.
175+
// Note: if `appType` is `'spa'` or `'mpa'`, Vite includes middlewares to handle
176+
// HTML requests and 404s so user middlewares should be added
177+
// before Vite's middlewares to take effect instead
178178
})
179179
}
180180

‎docs/config/shared-options.md

+10-4
Original file line numberDiff line numberDiff line change
@@ -336,9 +336,15 @@ Env variables starts with `envPrefix` will be exposed to your client source code
336336
`envPrefix` should not be set as `''`, which will expose all your env variables and cause unexpected leaking of of sensitive information. Vite will throw error when detecting `''`.
337337
:::
338338

339-
## spa
339+
## appType
340340

341-
- **Type:** `boolean`
342-
- **Default:** `true`
341+
- **Type:** `'spa' | 'mpa' | 'custom'`
342+
- **Default:** `'spa'`
343+
344+
Whether your application is a Single Page Application (SPA), a [Multi Page Application (MPA)](../guide/build#multi-page-app), or Custom Application (SSR and frameworks with custom HTML handling):
345+
346+
- `'spa'`: include SPA fallback middleware and configure [sirv](https://github.com/lukeed/sirv) with `single: true` in preview
347+
- `'mpa'`: only include non-SPA HTML middlewares
348+
- `'custom'`: don't include HTML middlewares
343349

344-
Whether your application is a Single Page Application (SPA). Set to `false` for other kinds of apps like MPAs. Learn more in Vite's [SSR guide](/guide/ssr#vite-cli).
350+
Learn more in Vite's [SSR guide](/guide/ssr#vite-cli). Related: [`server.middlewareMode`](./server-options#servermiddlewaremode).

‎docs/guide/ssr.md

+9-13
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,12 @@ const { createServer: createViteServer } = require('vite')
7474
async function createServer() {
7575
const app = express()
7676

77-
// Create Vite server in middleware mode. This disables Vite's own HTML
78-
// serving logic and let the parent server take control.
79-
//
80-
// In middleware mode, if you want to use Vite's own HTML serving logic
81-
// use `'html'` as the `middlewareMode` (ref https://vitejs.dev/config/#server-middlewaremode)
77+
// Create Vite server in middleware mode and configure the app type as
78+
// 'custom', disabling Vite's own HTML serving logic so parent server
79+
// can take control
8280
const vite = await createViteServer({
83-
server: { middlewareMode: 'ssr' }
81+
server: { middlewareMode: true },
82+
appType: 'custom'
8483
})
8584
// use vite's connect instance as middleware
8685
app.use(vite.middlewares)
@@ -267,11 +266,8 @@ In some cases like `webworker` runtimes, you might want to bundle your SSR build
267266
268267
## Vite CLI
269268
270-
The CLI commands `$ vite dev` and `$ vite preview` can also be used for SSR apps:
269+
The CLI commands `$ vite dev` and `$ vite preview` can also be used for SSR apps. You can add your SSR middlewares to the development server with [`configureServer`](/guide/api-plugin#configureserver) and to the preview server with [`configurePreviewServer`](/guide/api-plugin#configurepreviewserver).
271270
272-
1. Add your SSR middleware to the development server with [`configureServer`](/guide/api-plugin#configureserver) and to the preview server with [`configurePreviewServer`](/guide/api-plugin#configurepreviewserver).
273-
:::tip Note
274-
Use a post hook so that your SSR middleware runs _after_ Vite's middlewares.
275-
:::
276-
277-
2. Set `config.spa` to `false`. This switches the development and preview server from SPA mode to SSR/MPA mode.
271+
:::tip Note
272+
Use a post hook so that your SSR middleware runs _after_ Vite's middlewares.
273+
:::

‎packages/vite/src/node/config.ts

+33-6
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ export interface ConfigEnv {
5353
mode: string
5454
}
5555

56+
/**
57+
* spa: include SPA fallback middleware and configure sirv with `single: true` in preview
58+
*
59+
* mpa: only include non-SPA HTML middlewares
60+
*
61+
* custom: don't include HTML middlewares
62+
*/
63+
export type AppType = 'spa' | 'mpa' | 'custom'
64+
5665
export type UserConfigFn = (env: ConfigEnv) => UserConfig | Promise<UserConfig>
5766
export type UserConfigExport = UserConfig | Promise<UserConfig> | UserConfigFn
5867

@@ -215,11 +224,12 @@ export interface UserConfig {
215224
>
216225
}
217226
/**
218-
* Whether your application is a Single Page Application (SPA). Set to `false`
219-
* for other kinds of apps like MPAs.
220-
* @default true
227+
* Whether your application is a Single Page Application (SPA),
228+
* a Multi-Page Application (MPA), or Custom Application (SSR
229+
* and frameworks with custom HTML handling)
230+
* @default 'spa'
221231
*/
222-
spa?: boolean
232+
appType?: AppType
223233
}
224234

225235
export interface ExperimentalOptions {
@@ -302,7 +312,7 @@ export type ResolvedConfig = Readonly<
302312
/** @internal */
303313
packageCache: PackageCache
304314
worker: ResolveWorkerOptions
305-
spa: boolean
315+
appType: AppType
306316
}
307317
>
308318

@@ -507,6 +517,8 @@ export async function resolveConfig(
507517
else ssr = { target: 'node', format: 'cjs' }
508518
}
509519

520+
const middlewareMode = config?.server?.middlewareMode
521+
510522
const optimizeDeps = config.optimizeDeps || {}
511523

512524
const resolved: ResolvedConfig = {
@@ -552,7 +564,22 @@ export async function resolveConfig(
552564
}
553565
},
554566
worker: resolvedWorkerOptions,
555-
spa: config.spa ?? true
567+
appType: config.appType ?? middlewareMode === 'ssr' ? 'custom' : 'spa'
568+
}
569+
570+
if (middlewareMode === 'ssr') {
571+
logger.warn(
572+
colors.yellow(
573+
`server.middlewareMode 'ssr' is now deprecated, use server.middlewareMode true and appType 'custom'`
574+
)
575+
)
576+
}
577+
if (middlewareMode === 'html') {
578+
logger.warn(
579+
colors.yellow(
580+
`server.middlewareMode 'html' is now deprecated, use server.middlewareMode true`
581+
)
582+
)
556583
}
557584

558585
if (resolved.legacy?.buildRollupPluginCommonjs) {

‎packages/vite/src/node/preview.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export async function preview(
104104
sirv(distDir, {
105105
etag: true,
106106
dev: true,
107-
single: config.spa
107+
single: config.appType === 'spa'
108108
})
109109
)
110110

‎packages/vite/src/node/server/index.ts

+7-12
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ export interface ServerOptions extends CommonServerOptions {
100100

101101
export interface ResolvedServerOptions extends ServerOptions {
102102
fs: Required<FileSystemServeOptions>
103+
middlewareMode: boolean
103104
}
104105

105106
export interface FileSystemServeOptions {
@@ -268,10 +269,7 @@ export async function createServer(
268269
config.server.https,
269270
config.cacheDir
270271
)
271-
let { middlewareMode } = serverConfig
272-
if (middlewareMode === true) {
273-
middlewareMode = 'ssr'
274-
}
272+
const { middlewareMode } = serverConfig
275273

276274
const middlewares = connect() as Connect.Server
277275
const httpServer = middlewareMode
@@ -489,10 +487,8 @@ export async function createServer(
489487
middlewares.use(serveRawFsMiddleware(server))
490488
middlewares.use(serveStaticMiddleware(root, server))
491489

492-
const isMiddlewareMode = middlewareMode && middlewareMode !== 'html'
493-
494490
// spa fallback
495-
if (config.spa && !isMiddlewareMode) {
491+
if (config.appType === 'spa') {
496492
middlewares.use(spaFallbackMiddleware(root))
497493
}
498494

@@ -501,12 +497,10 @@ export async function createServer(
501497
// serve custom content instead of index.html.
502498
postHooks.forEach((fn) => fn && fn())
503499

504-
if (config.spa && !isMiddlewareMode) {
500+
if (config.appType === 'spa' || config.appType === 'mpa') {
505501
// transform index.html
506502
middlewares.use(indexHtmlMiddleware(server))
507-
}
508503

509-
if (!isMiddlewareMode) {
510504
// handle 404s
511505
// Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`
512506
middlewares.use(function vite404Middleware(_, res) {
@@ -516,7 +510,7 @@ export async function createServer(
516510
}
517511

518512
// error handler
519-
middlewares.use(errorMiddleware(server, !!middlewareMode))
513+
middlewares.use(errorMiddleware(server, middlewareMode))
520514

521515
const initOptimizer = async () => {
522516
if (isDepsOptimizerEnabled(config)) {
@@ -654,7 +648,8 @@ export function resolveServerOptions(
654648
): ResolvedServerOptions {
655649
const server: ResolvedServerOptions = {
656650
preTransformRequests: true,
657-
...(raw as ResolvedServerOptions)
651+
...(raw as ResolvedServerOptions),
652+
middlewareMode: !!raw?.middlewareMode
658653
}
659654
let allowDirs = server.fs?.allow
660655
const deny = server.fs?.deny || ['.env', '.env.*', '*.{crt,pem}']

‎playground/json/server.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@ async function createServer(
2020
root,
2121
logLevel: isTest ? 'error' : 'info',
2222
server: {
23-
middlewareMode: 'ssr',
23+
middlewareMode: true,
2424
watch: {
2525
// During tests we edit the files too fast and sometimes chokidar
2626
// misses change events, so enforce polling for consistency
2727
usePolling: true,
2828
interval: 100
2929
}
3030
},
31+
appType: 'custom',
3132
json: {
3233
stringify: true
3334
}

‎playground/optimize-missing-deps/server.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@ async function createServer(root = process.cwd(), hmrPort) {
1717
root,
1818
logLevel: isTest ? 'error' : 'info',
1919
server: {
20-
middlewareMode: 'ssr',
20+
middlewareMode: true,
2121
hmr: {
2222
port: hmrPort
2323
}
24-
}
24+
},
25+
appType: 'custom'
2526
})
2627
app.use(vite.middlewares)
2728

‎playground/ssr-deps/server.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export async function createServer(root = process.cwd(), hmrPort) {
2222
root,
2323
logLevel: isTest ? 'error' : 'info',
2424
server: {
25-
middlewareMode: 'ssr',
25+
middlewareMode: true,
2626
watch: {
2727
// During tests we edit the files too fast and sometimes chokidar
2828
// misses change events, so enforce polling for consistency
@@ -33,6 +33,7 @@ export async function createServer(root = process.cwd(), hmrPort) {
3333
port: hmrPort
3434
}
3535
},
36+
appType: 'custom',
3637
ssr: {
3738
noExternal: ['no-external-cjs']
3839
}

‎playground/ssr-html/server.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export async function createServer(root = process.cwd(), hmrPort) {
3737
root,
3838
logLevel: isTest ? 'error' : 'info',
3939
server: {
40-
middlewareMode: 'ssr',
40+
middlewareMode: true,
4141
watch: {
4242
// During tests we edit the files too fast and sometimes chokidar
4343
// misses change events, so enforce polling for consistency
@@ -47,7 +47,8 @@ export async function createServer(root = process.cwd(), hmrPort) {
4747
hmr: {
4848
port: hmrPort
4949
}
50-
}
50+
},
51+
appType: 'custom'
5152
})
5253
// use vite's connect instance as middleware
5354
app.use(vite.middlewares)

‎playground/ssr-pug/server.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export async function createServer(root = process.cwd(), hmrPort) {
3131
root,
3232
logLevel: isTest ? 'error' : 'info',
3333
server: {
34-
middlewareMode: 'ssr',
34+
middlewareMode: true,
3535
watch: {
3636
// During tests we edit the files too fast and sometimes chokidar
3737
// misses change events, so enforce polling for consistency
@@ -41,7 +41,8 @@ export async function createServer(root = process.cwd(), hmrPort) {
4141
hmr: {
4242
port: hmrPort
4343
}
44-
}
44+
},
45+
appType: 'custom'
4546
})
4647
// use vite's connect instance as middleware
4748
app.use(vite.middlewares)

‎playground/ssr-react/server.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export async function createServer(
3333
root,
3434
logLevel: isTest ? 'error' : 'info',
3535
server: {
36-
middlewareMode: 'ssr',
36+
middlewareMode: true,
3737
watch: {
3838
// During tests we edit the files too fast and sometimes chokidar
3939
// misses change events, so enforce polling for consistency
@@ -43,7 +43,8 @@ export async function createServer(
4343
hmr: {
4444
port: hmrPort
4545
}
46-
}
46+
},
47+
appType: 'custom'
4748
})
4849
// use vite's connect instance as middleware
4950
app.use(vite.middlewares)

‎playground/ssr-vue/server.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export async function createServer(
3737
root,
3838
logLevel: isTest ? 'error' : 'info',
3939
server: {
40-
middlewareMode: 'ssr',
40+
middlewareMode: true,
4141
watch: {
4242
// During tests we edit the files too fast and sometimes chokidar
4343
// misses change events, so enforce polling for consistency
@@ -47,7 +47,8 @@ export async function createServer(
4747
hmr: {
4848
port: hmrPort
4949
}
50-
}
50+
},
51+
appType: 'custom'
5152
})
5253
// use vite's connect instance as middleware
5354
app.use(vite.middlewares)

0 commit comments

Comments
 (0)
Please sign in to comment.