Rails作为API、Vite为前端服务时Vue前端无法渲染求助
解决Rails API + Vue + Vite 前后端无法连接、前端不渲染问题
核心问题
你的Rails应用是API模式,默认不会返回HTML视图;同时前端Vite服务和Rails后端没有正确的路由衔接,导致访问时直接返回API的JSON数据,而非前端页面。
具体修复步骤
1. 创建静态页面控制器
Rails API模式缺少返回HTML的控制器,需新增StaticController来返回前端的index.html:
rails generate controller Static index --skip-assets --skip-helper --skip-template-engine
修改app/controllers/static_controller.rb,让它继承ActionController::Base(而非API)以支持HTML渲染:
class StaticController < ActionController::Base def index render file: Rails.root.join('app/frontend/index.html'), layout: false end end
2. 调整Rails中间件配置
API模式会移除处理静态文件和HTML的中间件,打开config/application.rb,在现有配置中添加:
# 在config.api_only = true前后添加均可 config.middleware.use ActionDispatch::Static config.middleware.use Rack::Sendfile
3. 修正路由优先级
让所有非API的HTML请求都返回前端页面,修改config/routes.rb:
# 替换原root路由 root 'static#index' # API路由放在最前面 namespace :api do namespace :v1 do resources :chatrooms, only: %i[index] do resources :messages, only: %i[index create] end end end devise_for :users, controllers: { sessions: "users/sessions", registrations: "users/registrations" } resources :tracks resources :instruments, only: [:index, :new, :create] resources :genres, only: [:index, :new, :create] get '/index_results/:id', to: 'tracks#index_results', as: 'index_results' get '/my_tracks', to: 'tracks#myTracks', as: 'myTracks' get "/member-data", to: "members#show" # 兜底路由,确保所有HTML请求都返回前端页面 get "*path", to: "static#index", constraints: proc { |request| !request.xhr? && request.format.html? }
4. 修复Vite资源路径
在app/frontend/index.html中,修改script标签指向Vite开发服务的绝对路径:
<script type="module" src="http://localhost:3036/entrypoints/application.js"></script>
同时在Rails中配置内容安全策略,允许Vite资源加载,创建或修改config/initializers/content_security_policy.rb:
Rails.application.config.content_security_policy do |policy| if Rails.env.development? policy.connect_src :self, :https, 'http://localhost:3036' policy.script_src :self, :https, 'http://localhost:3036', :unsafe_eval, :unsafe_inline policy.style_src :self, :https, 'http://localhost:3036', :unsafe_inline end end
5. 修复Vue Router的Store初始化问题
router.js中的authGuard直接调用useSessionStore()时,Pinia还未完成初始化,会导致Vue无法挂载。修改router.js:
// 导入并创建Pinia实例 import { createPinia } from 'pinia' const pinia = createPinia() // 修改authGuard逻辑 const authGuard = (to, _from, next) => { const sessionStore = useSessionStore(pinia) const isLoggedIn = sessionStore.isLoggedIn const requiresAuth = to.meta.requiresAuth if (isLoggedIn && !requiresAuth) return next({ name: "Home" }) if (!isLoggedIn && requiresAuth) return next({ name: "Login" }) return next() }
6. 正确启动服务
- 第一个终端启动Vite:
vite dev - 第二个终端启动Rails:
rails s - 访问
http://localhost:3000,前端页面应该正常渲染
内容的提问来源于stack exchange,提问作者Maxime
相关产品推荐
相关产品推荐

