You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 21:32:32