如何在Vite中实现类似Webpack historyApiFallback的多入口路由重写(适配React生产构建)
如何在Vite中实现类似Webpack historyApiFallback的多入口路由重写(适配React生产构建)
嘿,我刚好踩过这个坑!从Webpack转Vite的时候,多入口的history fallback确实需要调整下配置,给你分享两种靠谱的方案,不管是开发环境还是生产构建都能让你的React应用正常hydrate:
方案一:用Vite原生的historyApiFallback配置(最简洁)
Vite的server.historyApiFallback其实和Webpack的配置逻辑几乎一致,支持rewrites规则,完全能满足你的需求。直接在Vite配置里加上这部分即可:
import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import path from 'path'; import { resolve } from 'path'; export default defineConfig({ root: path.resolve(__dirname, 'src'), base: '/', plugins: [react()], server: { // 开发环境的history fallback配置 historyApiFallback: { rewrites: [ // 匹配所有以/app开头的路径(包括/app本身),指向app.html { from: /^\/app\/?.*/, to: '/app.html' }, // 匹配所有以/arm开头的路径,指向arm.html { from: /^\/arm\/?.*/, to: '/arm.html' } ] } }, preview: { // 预览生产构建时的fallback配置,和开发环境一致即可 historyApiFallback: { rewrites: [ { from: /^\/app\/?.*/, to: '/app.html' }, { from: /^\/arm\/?.*/, to: '/arm.html' } ] } }, build: { sourcemap: true, outDir: resolve(__dirname, 'bundles'), rollupOptions: { input: { app: resolve(__dirname, 'src/app.html'), arm: resolve(__dirname, 'src/arm.html'), } } }, });
这样配置后:
- 访问
/app或/app/login都会返回app.html - 访问
/arm或/arm/settings都会返回arm.html
而且Vite会自动处理HTML里的JS/CSS资源引用,React能正常完成hydrate,不会出现只显示 raw HTML的问题。
方案二:自定义中间件(更灵活的场景)
如果你需要更复杂的路由判断逻辑,可以启用Vite的middlewareMode,通过自定义中间件来改写请求路径:
import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import path from 'path'; import { resolve } from 'path'; export default defineConfig({ root: path.resolve(__dirname, 'src'), base: '/', plugins: [react()], server: { middlewareMode: 'ssr', app: (req, res, next) => { const url = req.originalUrl; // 根据请求路径判断要指向的入口HTML if (url.startsWith('/app')) { req.url = '/app.html'; } else if (url.startsWith('/arm')) { req.url = '/arm.html'; } next(); } }, build: { sourcemap: true, outDir: resolve(__dirname, 'bundles'), rollupOptions: { input: { app: resolve(__dirname, 'src/app.html'), arm: resolve(__dirname, 'src/arm.html'), } } }, });
这个方式适合需要动态判断路由的场景,比如根据域名、请求参数来调整入口的情况。
生产部署注意事项
当你把构建后的代码部署到生产服务器(比如Nginx、Apache)时,还需要在服务器层面配置对应的路由重写,确保子路由能正确指向对应的HTML文件。以Nginx为例,添加以下配置:
server { # 其他配置... location /app { try_files $uri $uri/ /app.html; } location /arm { try_files $uri $uri/ /arm.html; } }
这样生产环境下,用户访问/app/login这类子路由时,服务器会返回app.html,React路由就能正常接管页面逻辑了。
为啥之前用插件没生效?
你之前尝试的插件方案失效,大概率是因为插件的重写逻辑没有正确关联Vite生成的入口HTML,导致返回的HTML文件里没有加载对应的React JS bundle,自然无法完成hydrate。而Vite原生的historyApiFallback会自动处理入口资源的引用,所以能保证React应用正常运行。
备注:内容来源于stack exchange,提问作者Рахат Мелисов
相关产品推荐
相关产品推荐

