Skip to content

Commit 69737f4

Browse files
bluwysapphi-red
andauthored
refactor(preview)!: use base middleware (#14818)
Co-authored-by: 翠 / green <[email protected]>
1 parent 42fee9e commit 69737f4

File tree

5 files changed

+40
-54
lines changed

5 files changed

+40
-54
lines changed

docs/guide/migration.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))
201201
There are some changes which only affect plugin/tool creators.
202202

203203
- [[#14119] refactor!: merge `PreviewServerForHook` into `PreviewServer` type](https://github.com/vitejs/vite/pull/14119)
204+
- The `configurePreviewServer` hook now accepts the `PreviewServer` type instead of `PreviewServerForHook` type.
205+
- [[#14818] refactor(preview)!: use base middleware](https://github.com/vitejs/vite/pull/14818)
206+
- Middlewares added from the returned function in `configurePreviewServer` now does not have access to the `base` when comparing the `req.url` value. This aligns the behaviour with the dev server. You can check the `base` from the `configResolved` hook if needed.
204207

205208
Also there are other breaking changes which only affect few users.
206209

packages/vite/src/node/preview.ts

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
} from './http'
1919
import { openBrowser } from './server/openBrowser'
2020
import compression from './server/middlewares/compression'
21+
import { baseMiddleware } from './server/middlewares/base'
2122
import { htmlFallbackMiddleware } from './server/middlewares/htmlFallback'
2223
import { indexHtmlMiddleware } from './server/middlewares/indexHtml'
2324
import { notFoundMiddleware } from './server/middlewares/notFound'
@@ -167,8 +168,10 @@ export async function preview(
167168

168169
app.use(compression())
169170

170-
const previewBase =
171-
config.base === './' || config.base === '' ? '/' : config.base
171+
// base
172+
if (config.base !== '/') {
173+
app.use(baseMiddleware(config.rawBase, false))
174+
}
172175

173176
// static assets
174177
const headers = config.preview.headers
@@ -190,36 +193,28 @@ export async function preview(
190193
},
191194
})(...args)
192195

193-
app.use(previewBase, viteAssetMiddleware)
196+
app.use(viteAssetMiddleware)
194197

195198
// html fallback
196199
if (config.appType === 'spa' || config.appType === 'mpa') {
197-
app.use(
198-
previewBase,
199-
htmlFallbackMiddleware(
200-
distDir,
201-
config.appType === 'spa',
202-
previewBase !== '/',
203-
),
204-
)
200+
app.use(htmlFallbackMiddleware(distDir, config.appType === 'spa'))
205201
}
206202

207203
// apply post server hooks from plugins
208204
postHooks.forEach((fn) => fn && fn())
209205

210206
if (config.appType === 'spa' || config.appType === 'mpa') {
211207
// transform index.html
212-
app.use(previewBase, indexHtmlMiddleware(distDir, server))
208+
app.use(indexHtmlMiddleware(distDir, server))
213209

214210
// handle 404s
215-
app.use(previewBase, notFoundMiddleware())
211+
app.use(notFoundMiddleware())
216212
}
217213

218214
const hostname = await resolveHostname(options.host)
219215
const port = options.port ?? DEFAULT_PREVIEW_PORT
220-
const protocol = options.https ? 'https' : 'http'
221216

222-
const serverPort = await httpServerStart(httpServer, {
217+
await httpServerStart(httpServer, {
223218
port,
224219
strictPort: options.strictPort,
225220
host: hostname.host,
@@ -233,14 +228,12 @@ export async function preview(
233228
)
234229

235230
if (options.open) {
236-
const path = typeof options.open === 'string' ? options.open : previewBase
237-
openBrowser(
238-
path.startsWith('http')
239-
? path
240-
: new URL(path, `${protocol}://${hostname.name}:${serverPort}`).href,
241-
true,
242-
logger,
243-
)
231+
const url = server.resolvedUrls?.local[0] ?? server.resolvedUrls?.network[0]
232+
if (url) {
233+
const path =
234+
typeof options.open === 'string' ? new URL(options.open, url).href : url
235+
openBrowser(path, true, logger)
236+
}
244237
}
245238

246239
return server as PreviewServer

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ export async function _createServer(
680680

681681
// base
682682
if (config.base !== '/') {
683-
middlewares.use(baseMiddleware(server))
683+
middlewares.use(baseMiddleware(config.rawBase, middlewareMode))
684684
}
685685

686686
// open in editor support

packages/vite/src/node/server/middlewares/base.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,39 @@
11
import type { Connect } from 'dep-types/connect'
2-
import type { ViteDevServer } from '..'
3-
import { joinUrlSegments, stripBase, withTrailingSlash } from '../../utils'
2+
import {
3+
cleanUrl,
4+
joinUrlSegments,
5+
stripBase,
6+
withTrailingSlash,
7+
} from '../../utils'
48

59
// this middleware is only active when (base !== '/')
610

7-
export function baseMiddleware({
8-
config,
9-
}: ViteDevServer): Connect.NextHandleFunction {
11+
export function baseMiddleware(
12+
rawBase: string,
13+
middlewareMode: boolean,
14+
): Connect.NextHandleFunction {
1015
// Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`
1116
return function viteBaseMiddleware(req, res, next) {
1217
const url = req.url!
13-
const parsed = new URL(url, 'http://vitejs.dev')
14-
const path = parsed.pathname || '/'
15-
const base = config.rawBase
18+
const pathname = cleanUrl(url)
19+
const base = rawBase
1620

17-
if (path.startsWith(base)) {
21+
if (pathname.startsWith(base)) {
1822
// rewrite url to remove base. this ensures that other middleware does
1923
// not need to consider base being prepended or not
2024
req.url = stripBase(url, base)
2125
return next()
2226
}
2327

2428
// skip redirect and error fallback on middleware mode, #4057
25-
if (config.server.middlewareMode) {
29+
if (middlewareMode) {
2630
return next()
2731
}
2832

29-
if (path === '/' || path === '/index.html') {
33+
if (pathname === '/' || pathname === '/index.html') {
3034
// redirect root visit to based url with search and hash
3135
res.writeHead(302, {
32-
Location: base + (parsed.search || '') + (parsed.hash || ''),
36+
Location: base + url.slice(pathname.length),
3337
})
3438
res.end()
3539
return

packages/vite/src/node/server/middlewares/htmlFallback.ts

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,7 @@ const debug = createDebugger('vite:html-fallback')
88
export function htmlFallbackMiddleware(
99
root: string,
1010
spaFallback: boolean,
11-
mounted = false,
1211
): Connect.NextHandleFunction {
13-
// When this middleware is mounted on a route, we need to re-assign `req.url` with a
14-
// leading `.` to signal a relative rewrite. Returning with a leading `/` returns a
15-
// buggy `req.url`. e.g.:
16-
//
17-
// mount /foo/bar:
18-
// req.url = /index.html
19-
// final = /foo/barindex.html
20-
//
21-
// mount /foo/bar:
22-
// req.url = ./index.html
23-
// final = /foo/bar/index.html
24-
const prepend = mounted ? '.' : ''
25-
2612
// Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`
2713
return function viteHtmlFallbackMiddleware(req, res, next) {
2814
if (
@@ -51,7 +37,7 @@ export function htmlFallbackMiddleware(
5137
const filePath = path.join(root, pathname)
5238
if (fs.existsSync(filePath)) {
5339
debug?.(`Rewriting ${req.method} ${req.url} to ${url}`)
54-
req.url = prepend + url
40+
req.url = url
5541
return next()
5642
}
5743
}
@@ -61,7 +47,7 @@ export function htmlFallbackMiddleware(
6147
if (fs.existsSync(filePath)) {
6248
const newUrl = url + 'index.html'
6349
debug?.(`Rewriting ${req.method} ${req.url} to ${newUrl}`)
64-
req.url = prepend + newUrl
50+
req.url = newUrl
6551
return next()
6652
}
6753
}
@@ -71,14 +57,14 @@ export function htmlFallbackMiddleware(
7157
if (fs.existsSync(filePath)) {
7258
const newUrl = url + '.html'
7359
debug?.(`Rewriting ${req.method} ${req.url} to ${newUrl}`)
74-
req.url = prepend + newUrl
60+
req.url = newUrl
7561
return next()
7662
}
7763
}
7864

7965
if (spaFallback) {
8066
debug?.(`Rewriting ${req.method} ${req.url} to /index.html`)
81-
req.url = prepend + '/index.html'
67+
req.url = '/index.html'
8268
}
8369

8470
next()

0 commit comments

Comments
 (0)