Blogger自作テンプレートのキャッシュ高速化
HTMLサイトマップに全記事のタイトルとurlとラベルと公開日を掲載することで、feedを使わずデータを取得できるようになります。Bloggerの自作テンプレートのカスタマイズはfeedを使って、データを取得して、feedで取得できないデータはBlogger公式ガジェットを使うしかありませんでした。
HTMLサイトマップから全記事のタイトルとurlとラベルと公開日を取得できれば、ほとんどのガジェットは自作できます。Blogger公式ガジェットは無駄にタグが多いので、自作すればタグもcssも少なくなります。Blogger標準javascriptを読み込む必要も無いので、その分だけ高速になります。
以前は以下のようなBlogger公式ガジェットを使っていました。
データベースが使えないときは普通はテキストファイルやcsvファイルで一覧を作ったり、htmlのキャッシュを保存して使いますが、Bloggerはサーバーにファイルをアップロードできないので、代わりにHTMLサイトマップを使います。
以前は投稿を表示すると、次ページと前ページのタイトル取得、関連記事に使用する同じラベルの最新の投稿の取得の3回feedを取得していました。feedには必要のない情報も多いので、無駄が多かったです。必要な情報だけのHTMLサイトマップページを1回読み込む方が高速になります。
feedを使うと、Google Search Consoleの「設定」の「クロールの統計情報」の「ページ リソースの読み込み」に大量にfeedのurlが並びます。Googleのクロール数は限られているので、「ページ リソースの読み込み」はHTMLサイトマップページだけにして、他のページをクロールしてもらった方がいいです。
HTMLサイトマップページにはコメントで公開日を設定しているので、データ取得用で公開日自体はHTMLサイトマップページに表示されません。
HTMLサイトマップページのファイル名は sitemap.html にしています。このブログの場合は https://googlebloggertrouble.blogspot.com/p/sitemap.html になります。
「ページ」にHTMLサイトマップページを作り、以下のjavascriptを貼り付けます。
HTMLサイトマップページを表示し、記事のタイトル部分を複数選択します。
firefoxの場合は右クリックして「選択した部分のソースを表示」を選ぶと、ソースが表示されます。<nav id="sitemappage">から</nav>までをコピーします。
Chromeの場合は右クリックして「検証」を選ぶと、ソースが表示されます。<nav id="sitemappage">を右クリックして「Copy」の「Copy Element」を選びます。
先ほどjavascriptを貼り付けたHTMLサイトマップページのjavascriptを消し、コピーした内容を貼り付け保存します。これで全記事のタイトルとurlと公開日のHTMLサイトマップページが完成します。
テンプレートの</body>の前に以下のjavascriptを追加することで、全ページでHTMLサイトマップページの内容を読み込むことができます。
HTMLサイトマップページを表示する場合はHTMLサイトマップページを読み込む必要が無いので、HTMLサイトマップページの場合の条件を追加し、処理をしないようにしています。
<b:if cond='data:blog.canonicalUrl != data:blog.canonicalHomepageUrl path "p/sitemap.html"'> と </b:if> がその部分です。少しでも読み込みを早くするために、HTMLサイトマップページに必要ない部分は同様に条件を追加します。
HTMLサイトマップページを読み込んだ後に配列にデータを格納しています。ALLLISTはタイトルとurlとラベルと公開日の配列、ALLURLLISTは1つのurlに複数のラベルがある場合のためにタイトルとurlだけを重複しないようにした配列です。
HTMLサイトマップを読み込んだ後の処理のjavascriptは以下になります。function mainMenu(){と}の間に、全記事のタイトルとurlとラベルと公開日を使って実行したいjavascriptの関数名を書きます。
キャッシュ高速化を使ったjavascriptは以下のようなものがあります。
HTMLサイトマップから全記事のタイトルとurlとラベルと公開日を取得できれば、ほとんどのガジェットは自作できます。Blogger公式ガジェットは無駄にタグが多いので、自作すればタグもcssも少なくなります。Blogger標準javascriptを読み込む必要も無いので、その分だけ高速になります。
以前は以下のようなBlogger公式ガジェットを使っていました。
<html>
<body>
<header>
「ページヘッダー」ガジェット
「ページリスト」ガジェット
</header>
<main>
「ブログの投稿」ガジェット
</main>
<aside>
「AdSense」ガジェット
「人気の投稿」ガジェット
「ラベル」ガジェット
「自己紹介」ガジェット
「ブログリスト」ガジェット
「ブログアーカイブ」ガジェット
「AdSense」ガジェット(2つ目)
</aside>
<footer>
「Attribution」ガジェット
</footer>
</body>
</html>
HTMLサイトマップを使いガジェットを自作した後のBlogger公式ガジェットはこんな感じです。
<html>
<body>
<header>
</header>
<main>
「ブログの投稿」ガジェット
</main>
<aside>
「人気の投稿」ガジェット
</aside>
<footer>
</footer>
</body>
</html>
データベースが使えないときは普通はテキストファイルやcsvファイルで一覧を作ったり、htmlのキャッシュを保存して使いますが、Bloggerはサーバーにファイルをアップロードできないので、代わりにHTMLサイトマップを使います。
以前は投稿を表示すると、次ページと前ページのタイトル取得、関連記事に使用する同じラベルの最新の投稿の取得の3回feedを取得していました。feedには必要のない情報も多いので、無駄が多かったです。必要な情報だけのHTMLサイトマップページを1回読み込む方が高速になります。
feedを使うと、Google Search Consoleの「設定」の「クロールの統計情報」の「ページ リソースの読み込み」に大量にfeedのurlが並びます。Googleのクロール数は限られているので、「ページ リソースの読み込み」はHTMLサイトマップページだけにして、他のページをクロールしてもらった方がいいです。
HTMLサイトマップページにはコメントで公開日を設定しているので、データ取得用で公開日自体はHTMLサイトマップページに表示されません。
HTMLサイトマップページのファイル名は sitemap.html にしています。このブログの場合は https://googlebloggertrouble.blogspot.com/p/sitemap.html になります。
「ページ」にHTMLサイトマップページを作り、以下のjavascriptを貼り付けます。
<nav id='sitemappage'></nav>
<script>
/*<![CDATA[*/
makeSiteMap();
async function makeSiteMap(){
let entrylist=new Array();
let entrylistlength=0;
for(let i=0;;i++){
await getSiteMap(entrylist,i);
if(entrylistlength==entrylist.length) break;
entrylistlength=entrylist.length;
}
let labellist=new Array();
for(let i=0;i<entrylist.length;i++) labellist[entrylist[i]['label']]=(labellist[entrylist[i]['label']]||0)+1;
entrylist.sort((a,b)=>{
if(a.title>b.title) return 1;
if(a.title<b.title) return -1;
return 0;
});
let html='';
for(label in labellist){
html+='<ul><li><a href="/search/label/'+encodeURIComponent(label)+'">'+label+'</a></li></ul>';
html+='<ol>';
for(let i=0;i<entrylist.length;i++){
if(entrylist[i]['label']==label){
html+='<li><a href="'+entrylist[i]['url'].split(location.hostname)[1]+'">'+entrylist[i]['title']+'</a><!--'+entrylist[i]['published']+'--></li>';
}
}
html+='</ol>';
}
document.getElementById('sitemappage').innerHTML=html;
}
async function getSiteMap(entrylist,count){
const queryMaxResults='150';
const feedUrl='/feeds/posts/summary?alt=json&max-results='+queryMaxResults+'&start-index='+(count*queryMaxResults+1);
await fetch(feedUrl)
.then(response=>response.json())
.then(json=>{
if(!json.feed.entry) return;
for(let i=0;i<json.feed.entry.length;i++){
let entry=json.feed.entry[i];
for(let j=0;j<entry.link.length;j++){
if(entry.link[j].rel=='alternate'){
for(let k=0;k<entry.category.length;k++){
entrylist.push({url:entry.link[j].href,title:entry.title.$t,label:entry.category[k].term,published:entry.published.$t});
}
break;
}
}
}
})
.catch(error=>console.log(error));
}
/*]]>*/
</script>
HTMLサイトマップページを表示し、記事のタイトル部分を複数選択します。
firefoxの場合は右クリックして「選択した部分のソースを表示」を選ぶと、ソースが表示されます。<nav id="sitemappage">から</nav>までをコピーします。
Chromeの場合は右クリックして「検証」を選ぶと、ソースが表示されます。<nav id="sitemappage">を右クリックして「Copy」の「Copy Element」を選びます。
先ほどjavascriptを貼り付けたHTMLサイトマップページのjavascriptを消し、コピーした内容を貼り付け保存します。これで全記事のタイトルとurlと公開日のHTMLサイトマップページが完成します。
テンプレートの</body>の前に以下のjavascriptを追加することで、全ページでHTMLサイトマップページの内容を読み込むことができます。
HTMLサイトマップページを表示する場合はHTMLサイトマップページを読み込む必要が無いので、HTMLサイトマップページの場合の条件を追加し、処理をしないようにしています。
<b:if cond='data:blog.canonicalUrl != data:blog.canonicalHomepageUrl path "p/sitemap.html"'> と </b:if> がその部分です。少しでも読み込みを早くするために、HTMLサイトマップページに必要ない部分は同様に条件を追加します。
HTMLサイトマップページを読み込んだ後に配列にデータを格納しています。ALLLISTはタイトルとurlとラベルと公開日の配列、ALLURLLISTは1つのurlに複数のラベルがある場合のためにタイトルとurlだけを重複しないようにした配列です。
<b:if cond='data:blog.canonicalUrl != data:blog.canonicalHomepageUrl path "p/sitemap.html"'>
<script>
/*<![CDATA[*/
function getUrlParam(key){
let searchlist=location.search.substring(1).split('&');
for(let i=0;i<searchlist.length;i++) if(searchlist[i].split('=')[0]==key) return decodeURI(searchlist[i].split('=')[1]);
return '';
}
const HOSTURL=location.protocol+'//'+location.hostname;
const NOWURL=location.protocol+'//'+location.hostname+location.pathname;
let SITEMAPURL='/p/sitemap.html';
if(getUrlParam('m')==1) SITEMAPURL=SITEMAPURL+'?m=1';
const ALLLIST=new Array();
const ALLURLLIST=new Array();
document.addEventListener('DOMContentLoaded',makeALLLIST);
function makeALLLIST(){
fetch(SITEMAPURL)
.then(response=>response.text())
.then(text=>{
let objlist=new DOMParser().parseFromString(text,"text/html").getElementById('sitemappage').getElementsByTagName('li');
let labelname='';
for(let i=0;i<objlist.length;i++){
let atag=objlist[i].getElementsByTagName('a')[0];
let pubtime=objlist[i].innerHTML.split('--')[1]||'';
if(!pubtime){
labelname=atag.textContent;
}else{
ALLLIST.push({url:HOSTURL+atag.getAttribute('href'),title:atag.textContent,label:labelname,published:pubtime});
ALLURLLIST[HOSTURL+atag.getAttribute('href')]=atag.textContent;
}
}
ALLLIST.sort((a,b)=>{
if(a.published<b.published) return 1;
if(a.published>b.published) return -1;
return 0;
});
mainMenu();
})
.catch(error=>console.log(error));
}
/*]]>*/
</script>
</b:if>
HTMLサイトマップを読み込んだ後の処理のjavascriptは以下になります。function mainMenu(){と}の間に、全記事のタイトルとurlとラベルと公開日を使って実行したいjavascriptの関数名を書きます。
<script>
function mainMenu(){
(javascriptの関数名)
}
</script>
キャッシュ高速化を使ったjavascriptは以下のようなものがあります。
blogger