标题和元标签未在服务器中的角度 SSR 中呈现

问题描述 投票:0回答:3

我在前端使用 Angular 6 开发了一个网站。默认情况下,Angular 对 SEO 不友好,因此为了做到这一点,我以 Angular-Universal 或 Angular SSR(服务器端渲染)的方式实现它。我更新了代码并比较了之前和现在的页面源,我可以在标签

<app-root>
</app-root>
中看到我的应用程序,之前只有“正在加载...”。

我正在使用

MetaService
中的
TitleService
@angular/platform-browser
分别更新 Facebook 和 Twitter 所需的
<meta>
标签以及
<title>
标签。

问题是当我在本地系统中运行节点服务器时,视图源显示了渲染的

meta
标签,但是当我在 AWS 虚拟机上的节点服务器中运行相同的代码时,我没有得到渲染的
meta 
标签,但其他应用程序代码可用。

更新: 添加

meta
标签

的功能
updateMetaTags(egElement: Elements[]) {
    this.url = 'https://example.com/eg/' + this.id;
    const title = egElement[1].innerHTML;
    this.tweetText = 'Check the latest blog on \"' + title + '\"';
    this.meta.addTags([
      { property: 'og:url', content: this.url },
      { property: 'og:type', content: 'website' },
      { property: 'og:title', content: title },
      { property: 'og:description', content: 'Author: ' + egElement[2].innerHTML },
      { property: 'og:image', content: this.egElement[3].img }
    ]);
  }

我在 ngOnInit() 中调用这个函数。它在我的本地计算机上正确渲染,但不在服务器上渲染。

egElement
id
从服务调用返回到后端,并且
meta
服务已导入并注入到构造函数中。

angular meta angular-universal server-side-rendering angular-seo
3个回答
4
投票

如果您使用自定义 XHR 调用,例如如果不使用 Angular HttpClient,SSR 将不会等待 API 调用响应(如果使用第 3 方库检索 API 数据,也可能会发生这种情况)。查看您的网站,除了页面布局/页眉/页脚之外,没有发生服务器端渲染

我猜测这与 SSR 中未检索到 API 数据有关。也许您可以用一些相关信息更新您的问题?

有一个经过良好测试和维护的库,称为

ngx-meta
,它是通用(SSR)兼容的。您可以查看他们的实现和演示,或者尝试一下他们的库 https://github.com/fulls1z3/ngx-meta


2
投票

嗨,我也遇到了这个错误,所以请确保在您的

server.ts
文件中导入
import 'reflect-metadata';
以将所有元反映到
index.html

你可以看看我的

server.ts
配置文件\

import 'zone.js/dist/zone-node';
import 'reflect-metadata';

import { enableProdMode } from '@angular/core';
// Express Engine
import { ngExpressEngine } from '@nguniversal/express-engine';
// Import module map for lazy loading
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';

import * as express from 'express';
import { join } from 'path';
import { readFileSync } from 'fs';

// Faster server renders w/ Prod mode (dev mode never needed)
enableProdMode();

// Express server
const app = express();

const PORT = process.env.PORT || 4000;
const DIST_FOLDER = join(process.cwd(), 'dist/browser');

const template = readFileSync(join(DIST_FOLDER, 'index.html')).toString();

const domino = require('domino');
const win = domino.createWindow(template);
global['localStorage'] = win.localStorage;
global['window'] = win;
global['document'] = win.document;
global['Document'] = win.document;
global['DOMTokenList'] = win.DOMTokenList;
global['Node'] = win.Node;
global['Text'] = win.Text;
global['HTMLElement'] = win.HTMLElement;
global['navigator'] = win.navigator;
global['MutationObserver'] = getMockMutationObserver();

function getMockMutationObserver() {
  return class {
    observe(node, options) {}

    disconnect() {}

    takeRecords() {
      return [];
    }
  };
}

// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main');

// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
app.engine(
  'html',
  ngExpressEngine({
    bootstrap: AppServerModuleNgFactory,
    providers: [provideModuleMap(LAZY_MODULE_MAP)],
  }),
);

app.set('view engine', 'html');
app.set('views', DIST_FOLDER);

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

// All regular routes use the Universal engine
app.get('*', (req, res) => {
  res.render('index', { req });
});

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

0
投票

基本上Server.ts文件负责执行服务器端渲染。流程就像首先 Server.ts 命中我们正在搜索的 url,然后将呈现结果,然后浏览器请求将再次命中该 url。如果我们在代码级别使用任何本地存储、会话存储、窗口,服务器将不会访问它们,因此流程将断开,并且仅呈现页面中的初始静态数据。如果服务器已经呈现页面,我们可以控制浏览器请求通过使用状态传输密钥机制。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.