1. 函数定义和配置解析
export async function preview(
inlineConfig: InlineConfig = {},
): Promise<PreviewServer> {
const config = await resolveConfig(
inlineConfig,
'serve',
'production',
'production',
true,
)
preview
函数接收一个可选的inlineConfig
参数,用于配置预览服务器。- 调用
resolveConfig
函数解析配置,返回一个config
对象。
2. 检查构建目录
const distDir = path.resolve(config.root, config.build.outDir)
if (
!fs.existsSync(distDir) &&
config.plugins.every((plugin) => !plugin.configurePreviewServer) &&
process.argv[1]?.endsWith(path.normalize('bin/vite.js')) &&
process.argv[2] === 'preview'
) {
throw new Error(
`The directory "${config.build.outDir}" does not exist. Did you build your project?`,
)
}
- 检查构建输出目录
distDir
是否存在。 - 如果没有插件实现
configurePreviewServer
钩子,并且是通过CLI调用的preview
命令,则抛出错误提示用户先构建项目。
3. 创建HTTP服务器
const app = connect() as Connect.Server
const httpServer = await resolveHttpServer(
config.preview,
app,
await resolveHttpsConfig(config.preview?.https),
)
setClientErrorHandler(httpServer, config.logger)
- 创建一个
connect
应用实例app
。 - 调用
resolveHttpServer
函数创建HTTP服务器httpServer
。 - 设置客户端错误处理函数。
4. 初始化服务器配置
const options = config.preview
const logger = config.logger
const closeHttpServer = createServerCloseFn(httpServer)
- 获取预览服务器的配置
options
和日志记录器logger
。 - 创建关闭HTTP服务器的函数
closeHttpServer
。
5. 定义预览服务器对象
const server: PreviewServer = {
config,
middlewares: app,
httpServer,
async close() {
teardownSIGTERMListener(closeServerAndExit)
await closeHttpServer()
},
resolvedUrls: null,
printUrls() {
if (server.resolvedUrls) {
printServerUrls(server.resolvedUrls, options.host, logger.info)
} else {
throw new Error('cannot print server URLs before server is listening.')
}
},
bindCLIShortcuts(options) {
bindCLIShortcuts(server as PreviewServer, options)
},
}
- 定义
PreviewServer
对象,包含配置、中间件、HTTP服务器等属性。 - 定义关闭服务器的方法
close
。 - 定义打印服务器URL的方法
printUrls
。 - 定义绑定CLI快捷键的方法
bindCLIShortcuts
。
6. 设置SIGTERM信号监听器
const closeServerAndExit = async () => {
try {
await server.close()
} finally {
process.exit()
}
}
setupSIGTERMListener(closeServerAndExit)
- 定义关闭服务器并退出的函数
closeServerAndExit
。 - 设置SIGTERM信号监听器,以便在接收到信号时关闭服务器并退出进程。
7. 应用插件钩子
const postHooks: ((() => void) | void)[] = []
for (const hook of config.getSortedPluginHooks('configurePreviewServer')) {
postHooks.push(await hook(server))
}
- 获取并应用所有插件的
configurePreviewServer
钩子。
8. 配置CORS和代理
const { cors } = config.preview
if (cors !== false) {
app.use(corsMiddleware(typeof cors === 'boolean' ? {} : cors))
}
const { proxy } = config.preview
if (proxy) {
app.use(proxyMiddleware(httpServer, proxy, config))
}
- 根据配置添加CORS中间件。
- 根据配置添加代理中间件。
9. 添加压缩和基础中间件
app.use(compression())
if (config.base !== '/') {
app.use(baseMiddleware(config.rawBase, false))
}
- 添加压缩中间件。
- 如果配置了基础路径,则添加基础中间件。
10. 静态资源和HTML回退中间件
const headers = config.preview.headers
const viteAssetMiddleware = (...args: readonly [any, any?, any?]) =>
sirv(distDir, {
etag: true,
dev: true,
extensions: [],
ignores: false,
setHeaders(res) {
if (headers) {
for (const name in headers) {
res.setHeader(name, headers[name]!)
}
}
},
shouldServe(filePath) {
return shouldServeFile(filePath, distDir)
},
})(...args)
app.use(viteAssetMiddleware)
if (config.appType === 'spa' || config.appType === 'mpa') {
app.use(htmlFallbackMiddleware(distDir, config.appType === 'spa'))
}
- 添加静态资源中间件
viteAssetMiddleware
。 - 根据应用类型添加HTML回退中间件。
11. 应用插件后钩子
postHooks.forEach((fn) => fn && fn())
- 执行所有插件的后钩子。
12. 添加index.html和404中间件
if (config.appType === 'spa' || config.appType === 'mpa') {
app.use(indexHtmlMiddleware(distDir, server))
app.use(notFoundMiddleware())
}
- 添加index.html中间件和404中间件。
13. 启动HTTP服务器
const hostname = await resolveHostname(options.host)
const port = options.port ?? DEFAULT_PREVIEW_PORT
await httpServerStart(httpServer, {
port,
strictPort: options.strictPort,
host: hostname.host,
logger,
})
server.resolvedUrls = await resolveServerUrls(
httpServer,
config.preview,
config,
)
- 解析主机名和端口。
- 启动HTTP服务器。
- 解析并设置服务器URL。
14. 打开浏览器
if (options.open) {
const url = server.resolvedUrls?.local[0] ?? server.resolvedUrls?.network[0]
if (url) {
const path =
typeof options.open === 'string' ? new URL(options.open, url).href : url
openBrowser(path, true, logger)
}
}
- 如果配置了自动打开浏览器,则打开浏览器并访问服务器URL。
15. 返回预览服务器对象
return server as PreviewServer
}
- 返回预览服务器对象。
总结
该代码定义了一个preview
函数,用于启动一个Vite预览服务器,模拟生产环境部署。主要功能包括:
- 解析配置并检查构建目录。
- 创建HTTP服务器和
connect
应用实例。 - 设置服务器关闭逻辑和SIGTERM信号监听器。
- 应用插件钩子和中间件(如CORS、代理、压缩、静态资源、HTML回退等)。
- 启动HTTP服务器并解析服务器URL。
- 根据配置自动打开浏览器。
- 返回预览服务器对象,提供关闭服务器、打印URL和绑定CLI快捷键等功能。