Angular 18 SSR部署Vercel Serverless时404页面异常问题
Angular 18 SSR部署Vercel Serverless后404页面异常修复方案
核心问题定位
运行时日志的TypeError: Cannot read properties of undefined (reading 'default'),根源是api/index.js中动态导入的处理错误——import()返回的是Promise,直接访问server.app会拿到undefined,导致Serverless函数崩溃抛出500错误。此外Vercel路由规则和server.ts的静态文件处理逻辑,也会影响Angular路由接管404。
分步修复
1. 修正Serverless入口文件(api/index.js)
将原错误的异步导入处理改为正确的异步导出:
module.exports = async (req, res) => { const { app } = await import('../dist/project/server/server.mjs'); app()(req, res); };
原因:import()是异步操作,必须等待Promise解析后才能获取导出的app函数,直接赋值server.app会在Promise未完成时拿到undefined,触发运行时错误。
2. 调整Vercel配置文件(vercel.json)
优化路由规则,避免静态文件请求被错误转发到Serverless函数:
{ "version": 2, "public": true, "name": "project", "devCommand": "node dist/project/server/server.mjs", "rewrites": [ { "source": "/(.*)", "destination": "/api", "has": [{"type": "header", "key": "accept", "value": "text/html"}] } ], "functions": { "api/index.js": { "includeFiles": "dist/project/**" } } }
原因:原规则会把所有请求(包括静态资源)都转发到Serverless函数,添加accept: text/html的条件,只让HTML请求走SSR逻辑,静态资源直接由Vercel托管,减少函数负载同时避免干扰。
3. 优化server.ts的错误处理逻辑
在Angular渲染失败时,明确返回404状态码,确保自定义404组件能正常触发:
// 修改server.get('**')的错误处理部分 server.get('**', (req, res, next) => { const { protocol, originalUrl, baseUrl, headers } = req; commonEngine .render({ bootstrap, documentFilePath: indexHtml, url: `${protocol}://${headers.host}${originalUrl}`, publicPath: browserDistFolder, providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }], }) .then((html) => res.send(html)) .catch((err) => { // 判断是否为路由未匹配的错误,返回404 if (err.message.includes('Cannot match any routes')) { res.status(404); // 重新渲染404页面 commonEngine.render({ bootstrap, documentFilePath: indexHtml, url: `${protocol}://${headers.host}/404`, publicPath: browserDistFolder, providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }], }).then(html => res.send(html)).catch(() => next(err)); } else { next(err); } }); });
原因:当Angular无法匹配路由时,会抛出错误,直接next(err)会让Express返回500,手动捕获并返回404状态码,同时渲染自定义404组件,确保前端能正确展示。
4. 确认Angular路由配置(app.routes.ts)
保持现有配置即可,确保通配符路由指向404组件:
export const routes: Routes = [ { path: '', redirectTo: '/home', pathMatch: 'full' }, { path: 'home', component: HomeComponent }, { path: '404', component: PageNotFoundComponent }, { path: '**', component: PageNotFoundComponent }, ];
验证步骤
- 本地重新编译:
ng build --ssr - 部署到Vercel:
vercel --prod - 访问无效URL,确认自定义404组件正常显示,无500错误。
内容的提问来源于stack exchange,提问作者The Segfault
相关产品推荐
相关产品推荐

