カテゴリー
【Angular】head要素内に配置したlink要素でCanonical Urlを書き換えるサービスクラスの実装方法
※ 当ページには【広告/PR】を含む場合があります。
2020/04/21
2022/08/10
細かいところですが、WebページのSEO対策でURLアドレスにCanonical名を設定することで、クローラーが正しくページを読み込んでインデックスを作成してくれるなどの利点が挙げられます。
Angularでウェブベージをフルスクラッチして作成する場合、なんとも悩ましいのはrouterのページ遷移とhead要素のcanonicalの動的変更の方法です。
基本的にはページが変われば、canonical urlの値は適切に変わる必要があります。
AngularのようにSPAに特化したフレームワークでは、そのままではこの値を変えることはありません。
...
<head>
<link rel="canonical" href="http://example.com/">
</head>
...
今回は上記のように動的に
canonical urlちなみに、何故ページごとに書き換えないと駄目なのかは、以下のページが詳しいので、そちらをご覧ください。
なお、記事内のプロジェクトは、angular7以降にて動作確認させております。
DOMにアクセスさせる
まずは、
CanonicalLinkServiceDOCUMENTDIこの
DOCUMENT@angular/commonまた使う場合には、
Inject import { Injectable, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
@Injectable({
providedIn: 'root'
})
export class CanonicalLinkService {
constructor(
@Inject(DOCUMENT) private dom
) { }
...
これで、直にhtmlの
headそれでは以降で、
<link>canonicalcanonical値を追加する関数を実装
ではまず、html内に存在する
<link>createCanonicalUrlCanonicalLinkService import { Injectable, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
@Injectable({
providedIn: 'root'
})
export class CanonicalLinkService {
//...中略
private createCanonicalUrl(url?: string) {
const canURL = url === undefined ? this.dom.URL : url;
const link: HTMLLinkElement = this.dom.createElement('link');
link.setAttribute('rel', 'canonical');
this.dom.head.appendChild(link);
link.setAttribute('href', canURL);
}
//...以下略
設定したいurl値があったら、新しく作成したlink要素に
rel="canonical"href="urlの値"これで無事、ページごとに
canonical<link>canonical同じ一つのページに2つ以上の
canonicallinkcanonical古いcanonical値を消す方法
上でも説明したように、このまま
createCanonicalUrlよって、古いものは残さないのように消去してくれる
refreshCanonicalUrl import { Injectable, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
@Injectable({
providedIn: 'root'
})
export class CanonicalLinkService {
//...中略
private refreshCanonicalUrl() {
const links = this.dom.head.getElementsByTagName('link');
for (const link of links) {
if (link.getAttribute('rel') === 'canonical') {
this.dom.head.removeChild(link);
}
}
}
private createCanonicalUrl(url?: string) {
this.refreshCanonicalUrl() // Refresh links from the head element
const canURL = url === undefined ? this.dom.URL : url;
const link: HTMLLinkElement = this.dom.createElement('link');
link.setAttribute('rel', 'canonical');
this.dom.head.appendChild(link);
link.setAttribute('href', canURL);
}
//...以下略
この
refreshCanonicalUrl参考1
【おまけ】HTMLCollection(getElementsByTagNameの返り値)をIterableにする
お手元の開発環境によっては、利用している
typescriptcore-js //...
const links = this.dom.head.getElementsByTagName('link');
for (const link of links) { //👈ここのイテレーションでエラー
if (link.getAttribute('rel') === 'canonical') {
this.dom.head.removeChild(link);
}
}
が
not iteralbeこれはバグではなく、
HTMLCollection要は、最近の
HTMLCollectionそこで
Array.prototype.slice.call //...
const links = Array.prototype.slice.call(this.dom.head.getElementsByTagName('link')); //Array化
for (const link of links) {
if (link.getAttribute('rel') === 'canonical') {
this.dom.head.removeChild(link);
}
}
またモダンな
tslintfor //...
const links = this.dom.head.getElementsByTagName('link');
for (let i = 0; i < links.length ; i++) {
if (links[i].getAttribute('rel') === 'canonical') {
this.dom.head.removeChild(links[i]);
}
}
以上、
HTMLCollection