Aspnet Blazor SEO支持

翻译文章,原文Search Engine Optimization (SEO)

SEO在任何网站中都起着至关重要的作用,特别是对于SPA而言更是如此。在这个指南中,提到SEO时,我们指的是技术方面,而不是非技术方面。我们只关注如何向搜索引擎提供您网站的信息。

您可以在GitHub上下载本主题中使用的示例代码

先决条件

本指南假定您对一下内容有基本理解:

SEO技术部分

SEO的技术部分的目标是根据请求的URL在标签中更改元数据标签。例如,当用户导航到新的组件时,<title>标签会发生变化。Blazor Server确实支持SEO。然而,Blazor Server的默认模板不支持SEO,您需要自己实现。

使用Blazor Server进行SEO时常见的错误

在为Blazor Server实施SEO时,有一些常见的错误需要避免。其中一些在开发阶段可能有效,但在生产阶段可能不起作用。

  1. 使用JS更改元数据标签: Blazor Server是一个在服务器上渲染的SPA框架,因此这种方法将不起作用。
  2. 尝试更新已呈现的HTML标签: Blazor Server是在Razor Pages之上渲染的,Razor Pages不是一个SPA框架,因此不支持更新已呈现的HTML标签。
翻译补充
  1. 缺乏关键元数据: 确保每个页面都有适当的元数据,如标题(<title>)、描述(<meta name="description" content="..." />)和关键词。
  2. 动态加载内容: 如果您使用JavaScript等技术在页面上动态加载内容,确保搜索引擎可以正确地抓取和索引这些内容。使用预渲染技术或服务器端渲染(SSR)可以有助于解决这个问题。
  3. 不友好的URL结构: 使用有意义、清晰且易于理解的URL结构。避免使用过长、难以理解的参数和动态生成的URL。
  4. 不合理的页面层次结构: 组织您的页面以便搜索引擎可以轻松地理解页面之间的关系。使用适当的HTML标记来定义页面的结构。忽略性能问题: 确保您的网站加载速度快,因为搜索引擎通常对速度较慢的网站排名较低。优化图像、减少HTTP请求和使用浏览器缓存可以提高性能。
  5. 不处理404错误: 确保当用户访问不存在的页面时,返回适当的404错误页面,而不是默认的错误页面。这有助于搜索引擎了解页面是否真的不存在。
  6. 不使用合适的标题结构: 使用适当的标题标签(<h1><h6>)来定义页面的标题结构。确保标题具有层次性,反映页面的内容结构。
  7. 忽略移动友好性: 确保您的网站在移动设备上有良好的用户体验,因为搜索引擎对移动友好性有所考虑,并可能根据此因素进行排名。

Blazor服务器的SEO实现

以下步骤是在Blazor Server中实施SEO的步骤。这些步骤使用本地的Blazor Server技术,无需第三方工具。

  1. 创建一个名为MetadataProvider.cs的服务;
  2. 创建爱你一个名为MetadataTransferService.cs的数据转换服务;
  3. 在Startup.cs中将这两个服务都添加为scoped服务。
  4. 创建一个名为Metadata.razor的组件。
  5. 使用MetadataTransferServiceMetadataProvider来初始化元数据。
  6. _Host.cshtml页面中使用Metadata.razor

创建服务

我们将要创建MetadataProviderMetadataTransferService服务。正如名称所示,MetadataProvider将提供路由及其元数据详细信息。您可以将数据存储在数据库中,并使用此类获取沿路由的元数据。这是我们MetadataProvider实现的一个示例。

public class MetadataProvider
{
    public Dictionary<string, MetadataValue> RouteDetailMapping { get; set; } = new()
    {
        {
            "/",
            new()
            {
                Title = "Blazor School Example",
                Description = "Visit more at https://blazorschool.com"
            }
        },
        {
            "/about",
            new()
            {
                Title = "About us",
                Description = "Email us: dotnetprotech@gmail.com - The DotNetPro team."
            }
        }
    };
}

下一步是创建MetadataTransferService服务。正如名称所示,MetadataTransferService将充当组件之间数据传输的服务。有关传输服务的更多信息,请参见组件交互。


public class MetadataTransferService : INotifyPropertyChanged, IDisposable
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string _title;

    public string Title
    {
        get => _title;
        set
        {
            _title = value;
            OnPropertyChanged();
        }
    }

    private string _description;
    private readonly NavigationManager _navigationManager;
    private readonly MetadataProvider _metadataProvider;

    public string Description
    {
        get => _description;
        set
        {
            _description = value;
            OnPropertyChanged();
        }
    }

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new(propertyName));
    }

    public MetadataTransferService(NavigationManager navigationManager, MetadataProvider metadataProvider)
    {
        _navigationManager = navigationManager;
        _metadataProvider = metadataProvider;
    }

    public void Dispose()
    {

    }
}

您需要两个接口:INotifyPropertyChangedIDisposable用于传输服务。INotifyPropertyChanged用于等同对待每个属性更改,您也可以为每个属性声明一个事件,但这个接口不是必需的。IDisposable也不是必需的,但建议使用它,因为您将订阅NavigationManagerLocationChanged事件,需要使用Dispose方法取消订阅该事件。添加UpdateMetadata方法以更新元数据。


private void UpdateMetadata(string url)
{
    var metadataValue = _metadataProvider.RouteDetailMapping.FirstOrDefault(vp => url.EndsWith(vp.Key)).Value;

    if (metadataValue is null)
    {
        metadataValue = new()
        {
            Title = "Default",
            Description = "Default"
        };
    }

    Title = metadataValue.Title;
    Description = metadataValue.Description;
}

订阅LocationChanged事件。


public MetadataTransferService(NavigationManager navigationManager, MetadataProvider metadataProvider)
{
    ...
    _navigationManager.LocationChanged += UpdateMetadata;
}

private void UpdateMetadata(object sender, LocationChangedEventArgs e)
{
    UpdateMetadata(e.Location);
}

public void Dispose()
{
    _navigationManager.LocationChanged -= UpdateMetadata;
}

您需要两个接口:INotifyPropertyChangedIDisposable,用于传输服务。INotifyPropertyChanged用于等同对待每个属性更改,您也可以为每个属性声明一个事件,但这个接口不是必需的。IDisposable也不是必需的,但建议使用它,因为您将订阅NavigationManagerLocationChanged事件,需要使用Dispose方法取消订阅该事件。添加UpdateMetadata方法以更新元数据。


public MetadataTransferService(NavigationManager navigationManager, MetadataProvider metadataProvider)
{
    ...
    UpdateMetadata(_navigationManager.Uri);
}

Startup.cs中注册两个文件。


public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddSingleton<MetadataProvider>();
    services.AddScoped<MetadataTransferService>();
}

MetadataProvider也可以是一个作用域服务。您应该根据您的情况选择最合适的方式,而不总是将其设置为单例,就像示例中一样。

创建一个metadata组件

Metadata.razor包含您想要在网站上显示的所有元数据标记。每个网站必须具有的一些基本标签是<title>Metadata.razor将使用传输服务中的数据来呈现HTML元素。这是我们的Metadata.razor`实现的一个示例。


@inject MetadataTransferService MetadataTransferService@implements IDisposable

<title>@MetadataTransferService.Title</title><meta name="description" content="@MetadataTransferService.Description" />

@code {
    protected override void OnInitialized()
    {
        MetadataTransferService.PropertyChanged += OnMetadataChanged;
    }

    private void OnMetadataChanged(object sender, PropertyChangedEventArgs e)
    {
        StateHasChanged();
    }

    public void Dispose()
    {
        MetadataTransferService.PropertyChanged -= OnMetadataChanged;
    }

使用metadata组件

一旦您拥有了Metadata.razor,您需要在_Host.cshtml中使用它。请记住,_Host.cshtml是一个Razor页面,而您的Metadata.razor是一个Razor组件。在Razor页面中使用Razor组件与在另一个Razor组件中使用Razor组件有些不同。请移除_Host.cshtml中现有的<title>标签。

<head>
    ...
    <component type="typeof(Metadata)" render-mode="ServerPrerendered"/>
</head>

发表回复

您的电子邮箱地址不会被公开。