【问题标题】:Angular2 - SEO - how to manipulate the meta descriptionAngular2 - SEO - 如何操作元描述
【发布时间】:2016-06-20 22:03:34
【问题描述】:

google 中的搜索结果通过 TitleTag 和 <meta name="description"..."/> 标签显示。 <title>-Tag 可通过 Angular2 编辑 how to change page title in angular2 router

剩下的是描述。

是否可以在 angular2 中编写一个指令来操作我页面的 <head> 部分中的元标记。
因此,根据所选路线,元描述会发生如下变化:

<meta name="description" content="**my description for this route**"/>

【问题讨论】:

    标签: seo angular meta-tags


    【解决方案1】:

    目前没有开箱即用的解决方案,只有一个未解决的问题来实现它https://github.com/angular/angular/issues/7438。

    你当然可以自己实现类似标题服务的东西,只需使用TitleService作为模板

    类似于Title 服务的Meta 服务正在开发中(目前只是一个拉取请求)。

    【讨论】:

    • 非常感谢。我想我会采用标题服务的方式
    • 在发布版本中有变化吗?我知道平台浏览器中有一个内置的标题服务,但有什么描述吗?
    • 不,到目前为止没有任何变化。
    • 此 PR 现已合并,是 4.0.0-beta.0 的一部分
    【解决方案2】:

    我开发并刚刚发布了@ngx-meta/core 插件,它在路由级别操作元标记,并允许在组件构造函数中以编程方式设置元标记。

    您可以在@ngx-meta/core github 存储库中找到详细说明。此外,源文件可能有助于引入自定义逻辑。

    【讨论】:

    • 我已经启动了实时 ng2-metadata,它工作正常,但是当我让谷歌抓取我的页面时,它仍然说我有重复的元标记。我还有什么需要做的吗?
    • 我认为您应该从您的 html 中删除“静态”标签。 ng2-metadata 将即时写入它们。
    • 非常适合我。非常感谢!
    • 当使用延迟加载的路由时,我发现 @RonaldPadur 这不起作用
    • @AngularM 延迟加载路由在 Angular 中是一个大问题,尤其是当您使用 ngtools 在 AoT 中编译应用程序时。 Angular 团队正在解决它的问题。
    【解决方案3】:

    从Angular4开始,你可以使用Angular Meta service。

    import { Meta } from '@angular/platform-browser';
    
    // [...]
    
    constructor(private meta: Meta) {}
    
    // [...]
    
    this.meta.addTag({ name: 'robots', content: 'noindex' });
    

    【讨论】:

    • 这会帮助谷歌正确索引标题和元标签吗?
    • 通过 Meta 添加/更新的标签没有被爬虫抓取,有没有办法解决这个问题?
    • 我想这一定是注定要与 Angular Universal 一起使用的。
    • 对不起,其实我不明白,在哪个文件,我要更新这段代码。
    • 这适用于 Angular Universal。以下是我所做的更改:github.com/kmturley/universal-starter/commit/…
    【解决方案4】:

    这是可能的。我在我的应用程序中实现了它,下面我提供了它是如何制作的描述。

    基本思路是使用Meta from @angular/platform-browser

    要动态更改特定的元标记,您必须:

    1. 使用removeTag(attrSelector: string) : void删除旧的 方法。
    2. 使用addTag(tag: MetaDefinition, forceCreation?: boolean) : HTMLMetaElement 方法添加新的。

    当路由器触发路由更改事件时,您必须这样做。

    注意:实际上index.html的头部还需要有默认的&lt;title&gt;...&lt;/title&gt;和&lt;meta name="description"..." content="..."/&gt;,所以在动态设置之前已经有一些静态内容了。

    我的app-routing.module.ts 内容:

    import 'rxjs/add/operator/filter';
    import 'rxjs/add/operator/map';
    import 'rxjs/add/operator/mergeMap';
    
    import { NgModule } from '@angular/core';
    import { RouterModule, Routes, Router, NavigationEnd, ActivatedRoute } from '@angular/router';
    
    import { StringComparisonComponent }  from '../module-string-comparison/string-comparison.component';
    import { ClockCalculatorComponent }  from '../module-clock-calculator/clock-calculator.component';
    
    import { Title, Meta } from '@angular/platform-browser';
    
    const routes: Routes = [
      {
        path: '', redirectTo: '/string-comparison', pathMatch: 'full',
        data: { title: 'String comparison title', metaDescription: 'String comparison meta description content' }
      },
      {
        path: 'string-comparison',  component: StringComparisonComponent,
        data: { title: 'String comparison title', metaDescription: 'String comparison meta description content' }
      },
      {
        path: 'clock-time-calculator',  component: ClockCalculatorComponent,
        data: { title: 'Clock time calculator title', metaDescription: 'Clock time calculator meta description content' }
      }
    ];
    
    @NgModule({
      imports: [ RouterModule.forRoot(routes) ],
      exports: [ RouterModule ]
    })
    
    export class AppRoutingModule {
    
      constructor(
        private router: Router,
        private activatedRoute: ActivatedRoute,
        private titleService: Title,
        private metaService: Meta
      ){
        //Boilerplate code to filter out only important router events and to pull out data object field from each route
        this.router.events
        .filter(event => event instanceof NavigationEnd)
        .map(() => this.activatedRoute)
        .map(route => {
            while (route.firstChild) route = route.firstChild;
            return route;
        })
        .filter(route => route.outlet === 'primary')
        //Data fields are merged so we can use them directly to take title and metaDescription for each route from them
        .mergeMap(route => route.data)
        //Real action starts there
        .subscribe((event) => {
            //Changing title
            this.titleService.setTitle(event['title']);
    
            //Changing meta with name="description"
            var tag = { name: 'description', content: event['metaDescription'] };
            let attributeSelector : string = 'name="description"';
            this.metaService.removeTag(attributeSelector);
            this.metaService.addTag(tag, false);
        });
      }
    
    }
    
    1. 可以看出,有一个额外的 data 对象字段用于 每条路线。它包含 title 和 metaDescription 字符串 这将用作标题和元标记内容。
    2. 在构造函数中,我们过滤掉路由器事件并订阅过滤后的事件 路由器事件。那里用的是rxjs,但其实没必要用。常规的if statements 和loops 可用于流、过滤器和映射。
    3. 我们还将我们的数据对象字段与我们的事件合并,这样我们就可以轻松地 使用 title 和 metaDescription 字符串等信息。
    4. 我们动态更改&lt;title&gt;...&lt;/title&gt; 和&lt;meta name="description"..." content="..."/&gt; 标签。

    效果:

    第一个组件

    第二个组件

    事实上,我目前使用这个解决方案的更复杂的版本,它还使用ngx-translate 来显示不同语言的不同标题和元描述。
    完整代码可在angular2-bootstrap-translate-website-starter 项目中找到。
    带有 ngx-translate 解决方案的 app-routing.module.ts 文件就在那里:app-routing.module.ts。

    还有使用相同解决方案的生产应用程序:http://www.online-utils.com。

    当然,这不是唯一的方法,可能还有更好的方法来做到这一点。但我测试了这个解决方案,它确实有效。

    事实上,解决方案与相应帖子中关于更改标题的解决方案非常相似:How to change page title in angular2 router。

    Angular 元文档:https://angular.io/docs/ts/latest/api/platform-browser/index/Meta-class.html。事实上,它们的信息量不是很大,我必须试验并研究真正的 .js 代码才能使这种动态元更改生效。

    【讨论】:

    • 我试过这个标签正在被添加,但在 facebook 上的 facebook 打开图上它没有显示。有什么办法解决吗?
    猜你喜欢
    • 2015-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-06
    • 1970-01-01
    • 2015-01-17
    • 1970-01-01
    相关资源
    最近更新 更多