Asynchrone API Response not server rendered with Angular SSR

139 Views Asked by At

I have an Angular SSR website, which works fine and fast. In the source code I can see everhyting is working as a expexted. However, there is one thing I break my head over all day long.

I have some API calls which would set the meta data in the website, like the og:title, description, image and the regular title and description.

I have a service which handles all that, and in the static html files everything works fine, but when I want to set these meta tags dynamically with data from the post content, I noticed that the meta data is set after the page is loaded. I can see the metatag is set in the console, but when I look in the source code, it just has the same (static) title from the homepage.

This is my code on the news-single.page.compontent.ts:

ngOnInit() {
    this.currentRoute = this.router.url;
    this.loadPost();
  }
 loadPost() {
    this.currentPostSub = this.postService.getPost(this.postId).subscribe({
          next: post => {
            this.post = post;
            this.updateMetaTags(this.post);
          },
          error: (error) => {
            console.error(error)
          }
        });
  }

  updateMetaTags(post: any) {
    const title = post.title.rendered;
    const metaUrl = post.yoast_head_json.og_url.replace('backend', 'www');
    const description = post.yoast_head_json.og_description;
    const image = post.better_featured_image.source_url;
    this.metaService.updateMetaTag(title, metaUrl, description, image);
  }

This ia how I fetch the Api calls on my server.ts


// The Express app is exported so that it can be used by serverless Functions.
export function app(): express.Express {
  const server = express();
  const distFolder = join(process.cwd(), 'dist/website/browser');
  const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';

  // Our Universal express-engine (found @ https://github.com/angular/universal/tree/main/modules/express-engine)
  server.engine('html', ngExpressEngine({
    bootstrap: AppServerModule
  }));

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

  server.get('/api/*', async (req: express.Request, res: express.Response) => {

    const params = req.query;
    
    const apiURL = `https://example.com/wp-json/wp/v2/${req.params[0]}`;

    try {
      const response = await axios.get(apiURL, {
        responseType: "json"
      });
      const data = response.data;
      res.json(data);
    } catch (error: any) {
      res.status(500).json({error: error.message});
    }

  });

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

  // All regular routes use the Universal engine
  server.get('*', (req, res) => {
    res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
  });

  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}`);
  });
}


I let the server.ts make the actual API calls, which works fine.

Everything is build with Angular 16.

I have looked the documentation, tried to cache with Cloudflare, asked ChatGPT, read all the StackOverflow items. Nothing can help me further. When I look in Facebook debug for an example, I got the 206 message.

0

There are 0 best solutions below