我想在呈现的服务器端检测对我的页面的当前请求-ssr
来自网络爬虫或普通用户。我想在网络搜寻器中做一些事情,而不是当它是用户时做。当Web搜寻器正在访问页面以获取完整数据时,我想运行ng-in-viewport
。但是当用户使用我的页面时不运行。如何发现这个东西?
最近,我面临着和您一样的挑战。我为Angular应用程序使用了SSR,并且我使用StateTransfer,以避免在用户刚刚看到来自服务器的渲染内容后在浏览器中进行相同的API调用。
我有一个视图计数器,并且由于页面是在服务器端呈现的,所以我希望避免计算爬网程序生成的视图。
所以,我最终得到的是:
在server.ts
(这是Angular SSR的标准生成文件)中,确保您要从express传递请求对象,我这样子:
server.get('*', (req, res) => {
res.render(indexHtml, {
req, // Express request
res, // Express response
providers: [
{ provide: APP_BASE_HREF, useValue: req.baseUrl },
],
});
});
然后在您希望保留常量的任何constants.ts
中,添加VIEWER
注入令牌和可能的搜寻器列表:
export const VIEWER = new InjectionToken<string>('viewer');
export const CRAWLER_AGENTS = [
'googlebot', 'yandexbot', 'yahoo', 'bingbot',
'baiduspider', 'facebookexternalhit', 'twitterbot', 'rogerbot',
'linkedinbot', 'embedly', 'quora link preview', 'showyoubot', 'outbrain',
'pinterest/0.', 'developers.google.com/+/web/snippet',
'slackbot', 'vkshare', 'w3c_validator', 'redditbot', 'applebot',
'whatsapp', 'flipboard', 'tumblr', 'bitlybot', 'skypeuripreview',
'nuzzel', 'discordbot', 'google page speed'
];
然后在我的提供程序的app.module.ts
中,我添加了新的提供程序,它将包含有关机器人或用户的信息:
import { NgModule, Optional, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { REQUEST } from '@nguniversal/express-engine/tokens';
import { CRAWLER_AGENTS, VIEWER } from './constants';
@NgModule({
imports: [ /* ... */ ],
declarations: [ /* ... */ ],
providers: [
{
provide: VIEWER,
useFactory: viewerFactory,
deps: [PLATFORM_ID, [new Optional(), REQUEST]],
},
],
})
export class AppModule {}
export function viewerFactory(platformId, req: Request): string {
if (isPlatformBrowser(platformId)) {
return 'user';
}
const userAgent = (req.get('user-agent') || '').toLowerCase();
const isCrawler = CRAWLER_AGENTS.some(crawlerAgent => userAgent.indexOf(crawlerAgent) !== -1);
return isCrawler ? 'bot' : 'user';
}
是,根据Angular documentation,您可以将提供者的依赖项作为数组传递。我们需要Optional
来防止应用程序在客户端崩溃。显然,Express请求对象不存在。
然后在页面组件中,您可以像这样检查查看器:
import { Component, Inject, Optional } from '@angular/core';
@Component({
selector: 'app-article-page',
templateUrl: './article-page.component.html',
styleUrls: ['./article-page.component.scss'],
})
export class ArticlePageComponent {
constructor(
@Optional() @Inject(VIEWER) private viewer,
) {
const countViews = this.viewer !== 'bot';
}
}
请,如果您发现我的回答有用,请不要忘记将其标记为接受。