17
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

BlazorAdvent Calendar 2019

Day 7

Blazor で、タイトルや OGP 用メタ要素を設定する

Last updated at Posted at 2019-12-06

document.title を設定したい!

Blazor アプリを開発してて、ページ (ドキュメント) のタイトル (ブラウザのタブに表示されるテキストですね) を、コンポーネントごとに設定したいことってありませんか?

image.png

残念ながら、Blazor 上の標準的な C# コードだけでは、これは実現できないはず、です。

というのも、Blazor というかそのコンポーネントのレンダリング対象は、<app> 要素の内部の DOM に限られているためです。

image.png

なので、<app> 要素の外側というか親側というか、とにかく <head> 要素は普通には Blazor で扱えません。

ではどうするかといえば、Blazor 上の C# コードから JavaScript 相互運用機能を利用して、JavaScript に頼る必要があります。

document.title = "ここにC#コードから渡された値が来るように実装する(詳細略)"

とはいえ、自前でこれを実装するのは、不可能ではないにせよ、面倒な仕事です。

ということで、内部的には上記の仕組みでタイトルを変更することのできる Blazor コンポーネント "Blazor Head Element Helper" を、NuGet パッケージとして公開しております!

"Blazor Head Element Helper" の使い方

まずは "Blazor Head Element Helper" NuGet パッケージ (パッケージ ID は "Toolbelt.Blazor.HeadElement") をプロジェクトに追加します。

> dotnet add package Toolbelt.Blazor.HeadElement --version 1.0.0

次に、対象の Blazor アプリの Startup.ConfigureServices() にて、"Head Element Helper" のサービスを DI 機構に登録します。

using Toolbelt.Blazor.Extensions.DependencyInjection; // <- この行を追加し...

public class Startup
{
  public void ConfigureServices(IServiceCollection services)
  {
    services.AddHeadElementHelper(); // <- この行を追加する。
    ...

ここまで準備できたらいよいよコンポーネント側のコーディングに移るのですが、その前に、_Import.razor ファイルで、"Toolbelt.Blazor.HeadElement" 名前空間を既定で開いておくとよいです。

@* This is "_Imports.razor" *@
...
@using Toolbelt.Blazor.HeadElement

こうしておけば、見事、いずれのコンポーネントでも、下記のように <Title> コンポーネントを置いておくだけで、そのコンポーネントがレンダリングされるときは、そのページのタイトルが設定されるようになります!

@* This is "Pages/Counter.razor" *@
@page "/counter"

<Title>Counter (@currentCount)</Title>

movie-001.gif

さらにおまけで、タイトルだけでなく、<head> 要素内の <meta> 要素も、設定可能です!

<Meta Property="ogp:title" Content="Counter" />

これで OGP 対応もバッチリですね!
...?

サーバー側事前レンダリングは...?

ちょっと待って下さい。

各種検索クローラや SNS サーバーからは、結局、最初の HTTP GET 要求でサーバーから返されたコンテンツしか見えません。

ですので冒頭で説明したとおり、JavaScript で動的にタイトルやメタ要素を変更しているだけなら、まったく OGP 対応になってませんね!
image.png

しかしご安心を。

サーバー側 (クライアントサイド Blazor の場合は、ASP.NET Core ホスティングが必要) に "Toolbelt.Blazor.HeadElement.ServerPrerendering" NuGet パッケージを追加してみて下さい。

> dotnet add package Toolbelt.Blazor.HeadElement.ServerPrerendering

その上で、サーバー側 Startup.Configure() メソッド内にて、app.UseStaticFiles() より前の行に、"Head Element Server Prerendering" ミドルウェアの登録行を追加します。

using Toolbelt.Blazor.Extensions.DependencyInjection; // <- この行を追加し...

public class Startup
{
  public void Configure(IApplicationBuilder app)
  {
    app.UseHeadElementServerPrerendering(); // <- この行を "app.UseStaticFile" より前に追加。
    ...
    app.UseStaticFiles()
    ...

すると、あら不思議!

HTTP GET 要求で返される HTML コンテンツ内の <title> 要素や <meta> 要素群が、.razor ファイル内で <Title> コンポーネントや <Meta> コンポーネントで実装したとおりの内容になっている
はずです。

image.png

よかったよかった。

デモンストレーションサイト

下記に、"Blazor Head Element Helper" とそのサーバー側事前レンダリング機能を利用したデモンストレーションサイトを公開してます。

実際にこのデモンストレーションサイトに掲載している各観光ポイントページの URL を Twiiter にツイートしたりしてみると、ちゃんと Twitter カード形式で表示されるはず、です (下記)。

このデモンストレーションサイトのソースコードは下記で閲覧可能です。

"Blazor Head Element Helper" は、サーバーサイド Blazor (Blazor Server App)、クライアントサイド Blazor (Blazor WebAssembly App) のいずれのホスティングモデルでも動作します。

これで Blazor アプリでも、OGP 対応できますね!

Happy Coding! :)

17
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?