Angular SSR配置Express POST路由失败,请求遭Angular路由拦截
解决Angular 18 SSR中API路由被前端路由接管的问题
核心问题原因
Express路由匹配按顺序执行,若把Angular静态文件服务、SSR路由放在API路由之前,所有请求会先被Angular路由处理,导致/api/login这类请求被判定为前端路由抛出NG04002错误;同时Vite开发环境会将/api路径识别为前端资源路径,进而报错找不到polyfills.js、main.js。
解决方案步骤
1. 调整server.ts的路由顺序
必须让API路由挂载在Angular相关服务之前,确保Express优先处理/api开头的请求:
import { APP_BASE_HREF } from '@angular/common'; import { CommonEngine } from '@angular/ssr'; import express from 'express'; import { fileURLToPath } from 'node:url'; import { dirname, join, resolve } from 'node:path'; import authRoutes from './auth.routes'; const app = express(); const serverDistFolder = dirname(fileURLToPath(import.meta.url)); const browserDistFolder = resolve(serverDistFolder, '../browser'); const indexHtml = join(serverDistFolder, 'index.server.html'); // 1. 先启用JSON解析中间件 app.use(express.json()); // 2. 优先挂载API路由 app.use('/api', authRoutes); // 3. 再配置Angular静态文件服务 app.use(express.static(browserDistFolder, { maxAge: '1y', index: 'index.html', })); // 4. 最后配置Angular SSR引擎路由 const commonEngine = new CommonEngine(); app.get('*', (req, res, next) => { const { protocol, originalUrl, baseUrl, headers } = req; commonEngine .render({ bootstrap: () => import('./src/main.server'), documentFilePath: indexHtml, url: `${protocol}://${headers.host}${originalUrl}`, publicPath: browserDistFolder, providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }], }) .then((html) => res.send(html)) .catch((err) => next(err)); }); const port = process.env['PORT'] || 4000; app.listen(port, () => { console.log(`Node Express server listening on http://localhost:${port}`); });
2. 配置Vite开发环境代理
在vite.config.ts中添加代理规则,将/api请求转发到Express服务器端口,避免Vite误判为前端资源:
import { defineConfig } from 'vite'; import angular from '@angular/vite-plugin-angular'; export default defineConfig({ plugins: [angular()], server: { proxy: { '/api': { target: 'http://localhost:4000', changeOrigin: true, }, }, }, });
3. 验证前端请求写法
确保前端fetch请求路径正确,示例:
async login(username: string, password: string) { const response = await fetch('/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ username, password }), }); return response.json(); }
内容的提问来源于stack exchange,提问作者NiceToMytyuk
相关产品推荐
相关产品推荐

