我已经在前端使用Angular 6开发了一个网站。默认情况下,Angular不是SEO友好的,因此,为了做到这一点,我以Angular-Universal或Angular SSR(服务器端渲染)的方式实现了它。我更新了代码,并从现在开始比较了页面源代码,在只有“加载...”出现之前,我可以在标签<app-root>
和</app-root>
中看到我的应用程序。
我正在使用MetaService
中的TitleService
和@angular/platform-browser
来分别更新Facebook和Twitter所需的<meta>
标签和<title>
标签。
问题是,当我在本地系统中运行节点服务器时,视图源向我显示了呈现的meta
标签,但是当我在AWS VM上的节点服务器中运行相同的代码时,却没有呈现的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
服务已导入并注入到构造函数中。
答案 0 :(得分:1)
如果您使用自定义XHR调用,例如如果不使用Angular HttpClient,则SSR不会等待API调用响应(如果使用第三方库检索API数据,也会发生这种情况)。查看您的网站,除了页面布局/页眉/页脚
之外,没有服务器端渲染发生我猜这与未在SSR中检索到的API数据有关。也许您可以使用一些有关此信息的信息来更新您的问题?
有一个经过测试和维护的库,名为ngx-meta
,具有通用(SSR)兼容性。您可以查看它们的实现和演示,也可以尝试使用它们的库https://github.com/fulls1z3/ngx-meta
答案 1 :(得分:1)
嗨,我也遇到了此错误,因此请确保您的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}`);
});