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时,有一些常见的错误需要避免。其中一些在开发阶段可能有效,但在生产阶段可能不起作用。
- 使用JS更改元数据标签: Blazor Server是一个在服务器上渲染的SPA框架,因此这种方法将不起作用。
- 尝试更新已呈现的HTML标签: Blazor Server是在Razor Pages之上渲染的,Razor Pages不是一个SPA框架,因此不支持更新已呈现的HTML标签。
翻译补充
- 缺乏关键元数据: 确保每个页面都有适当的元数据,如标题(
<title>
)、描述(<meta name="description" content="..." />
)和关键词。 - 动态加载内容: 如果您使用JavaScript等技术在页面上动态加载内容,确保搜索引擎可以正确地抓取和索引这些内容。使用预渲染技术或服务器端渲染(SSR)可以有助于解决这个问题。
- 不友好的URL结构: 使用有意义、清晰且易于理解的URL结构。避免使用过长、难以理解的参数和动态生成的URL。
- 不合理的页面层次结构: 组织您的页面以便搜索引擎可以轻松地理解页面之间的关系。使用适当的HTML标记来定义页面的结构。忽略性能问题: 确保您的网站加载速度快,因为搜索引擎通常对速度较慢的网站排名较低。优化图像、减少HTTP请求和使用浏览器缓存可以提高性能。
- 不处理404错误: 确保当用户访问不存在的页面时,返回适当的404错误页面,而不是默认的错误页面。这有助于搜索引擎了解页面是否真的不存在。
- 不使用合适的标题结构: 使用适当的标题标签(
<h1>
到<h6>
)来定义页面的标题结构。确保标题具有层次性,反映页面的内容结构。 - 忽略移动友好性: 确保您的网站在移动设备上有良好的用户体验,因为搜索引擎对移动友好性有所考虑,并可能根据此因素进行排名。
Blazor服务器的SEO实现
以下步骤是在Blazor Server中实施SEO的步骤。这些步骤使用本地的Blazor Server技术,无需第三方工具。
- 创建一个名为
MetadataProvider.cs
的服务; - 创建爱你一个名为
MetadataTransferService.cs
的数据转换服务; - 在Startup.cs中将这两个服务都添加为scoped服务。
- 创建一个名为
Metadata.razor
的组件。 - 使用
MetadataTransferService
和MetadataProvider
来初始化元数据。 - 在
_Host.cshtml
页面中使用Metadata.razor
。
创建服务
我们将要创建MetadataProvider
和MetadataTransferService
服务。正如名称所示,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()
{
}
}
您需要两个接口:INotifyPropertyChanged
和IDisposable
用于传输服务。INotifyPropertyChanged
用于等同对待每个属性更改,您也可以为每个属性声明一个事件,但这个接口不是必需的。IDisposable
也不是必需的,但建议使用它,因为您将订阅NavigationManager
的LocationChanged
事件,需要使用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;
}
您需要两个接口:INotifyPropertyChanged
和IDisposable
,用于传输服务。INotifyPropertyChanged
用于等同对待每个属性更改,您也可以为每个属性声明一个事件,但这个接口不是必需的。IDisposable
也不是必需的,但建议使用它,因为您将订阅NavigationManager
的LocationChanged
事件,需要使用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>
发表回复