1

I can't make my 404 page using Angular SSR deployed on Vercel Serveless Function

When accessing a bad url supposed to be 404 have this error This Serverless Function has crashed. its a 500 internal server error

I am new to vercel and new to angular SSR so its hard for me to figure out how it is supposed to work, before using a serverless function I was trying to make my 404 work and it was also not working it was just doing the vercel 404 page instead of redirecting to my angular /404 it felt like my server.ts coudnt handle 404 and give it to my angular app and was throwing even before my app knew about it so my angular app routing could never do the job of redirecting to the correct /404 or just display the 404 component

It works locally ng serve (logic because its not using server.ts)

It also works doing node dist/project/server/server.mjs (after a build using server.ts)

Here is my server.ts is angular standard

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 bootstrap from './src/main.server';

// The Express app is exported so that it can be used by serverless Functions.
export function app(): express.Express {
  const server = express();
  const serverDistFolder = dirname(fileURLToPath(import.meta.url));
  const browserDistFolder = resolve(serverDistFolder, '../browser');
  const indexHtml = join(serverDistFolder, 'index.server.html');

  const commonEngine = new CommonEngine();

  server.set('view engine', 'html');
  server.set('views', browserDistFolder);

  // Example Express Rest API endpoints
  // server.get('/api/**', (req, res) => { });
  // Serve static files from /browser
  server.get(
    '**',
    express.static(browserDistFolder, {
      maxAge: '1y',
      index: 'index.html',
    }),
  );

  // All regular routes use the Angular engine
  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) => next(err));
  });

  return server;
}

function run(): void {
  const port = process.env['PORT'] || 4000;

  // Start up the Node server
  const server = app();
  server.listen(port, () => {
    console.log(`Node Express server listening on http://localhost:${port}`);
  });
}

run();

My vercel deployment is pretty straightforward

{
  "version": 2,
  "public": true,
  "name": "project",
  "devCommand": "node dist/project/server/server.mjs",
  "rewrites": [
    { "source": "/(.*)", "destination": "/api" }
  ],
  "functions": {
    "api/index.js": {
      "includeFiles": "dist/project/**"
    }
  }
}

I have a folder api/ with index.js

const server = import('../dist/project/server/server.mjs');

module.exports = server.app;

My app.routes.ts are setup correctly

export const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'home', component: HomeComponent },
  { path: '404', component: PageNotFoundComponent }, // I have this because I tried doing a redirectTo: '/404' but it didnt change anything
  { path: '**', component: PageNotFoundComponent },
];

Here is the runtime error:

    TypeError: Cannot read properties of undefined (reading 'default')
    at c (/opt/rust/nodejs.js:8:13746)
    at /opt/rust/nodejs.js:8:13963
    at new Promise (<anonymous>)
    at Pt (/opt/rust/nodejs.js:8:13037)
    at nn (/opt/rust/nodejs.js:9:78)
    at Object.<anonymous> (/opt/rust/nodejs.js:9:478)
    at Module._compile (node:internal/modules/cjs/loader:1358:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1416:10)
    at Module.load (node:internal/modules/cjs/loader:1208:32)
    at Module._load (node:internal/modules/cjs/loader:1024:12)
Node.js process exited with exit status: 1. The logs above can help with debugging the issue.
INIT_REPORT Init Duration: 174.56 ms    Phase: invoke   Status: error   Error Type: Runtime.ExitError

1 Answer 1

1

I made it work.....

api/index.js

export default import('../dist/project/server/server.mjs')
  .then(module => module.app());

vercel.json

{
  "version": 2,
  "public": true,
  "name": "project",
  "rewrites": [
    {
      "source": "/(.*)",
      "destination": "/api"
    }
  ],
  "functions": {
    "api/index.js": {
      "includeFiles": "dist/project/**"
    }
  }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.