Blogger自作テンプレートのキャッシュ高速化

HTMLサイトマップに全記事のタイトルとurlとラベルと公開日を掲載することで、feedを使わずデータを取得できるようになります。Bloggerの自作テンプレートのカスタマイズはfeedを使って、データを取得して、feedで取得できないデータはBlogger公式ガジェットを使うしかありませんでした。

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は以下のようなものがあります。
  1. Blogger自作ラベルリスト・キャッシュ高速化
  2. Blogger自作アーカイブリスト・キャッシュ高速化
  3. Blogger自作おすすめリスト・キャッシュ高速化
  4. Blogger自作次ページタイトル設定・キャッシュ高速化
  5. Blogger自作最新記事と関連記事リスト・キャッシュ高速化
  6. Blogger自作SNSボタン・キャッシュ高速化
  7. Blogger自作ページネーション・キャッシュ高速化
この記事のタイトルとURLをコピーする blogger
blogger