MENU CLOSE

barba.js [v2]で簡単に非同期画面遷移を取り入れてページ高速化!

JavaScript

barba.jsって?

端的に言うと非同期画面遷移が簡単にできるライブラリ。
このサイトでも使っていますが、デモも作ってみました。

DEMO

最近はREST API + フレームワークなどで簡単にサクサク見れるSPA(Single Page Application)を作れるようになりました。しかし通常のコーポレートサイトやブログメディアサイトなどにSEOを考えた上でサクッとSPAを取り入れることは難易度が高く、SSRなど余計なことを考え出すと工数と合わないので僕はなかなか手が出ません。(Vue.jsなどはSSRしなくてもGoogleがちゃんとレンダリングしてくれる説もありますが)

それでも快適にかっこよくシュバっとページ遷移したい!という思いで方法を探していると「Barba.js」にたどり着きました。弊社HPやこのサイトでも使っていますが、SPAを作成するより非常に少ない工数で簡単にアニメーション付きの非同期遷移ができます。もちろんSEOにも対応できます。

では使い方を見ていきます。

使い方

公式のドキュメントはこちらです。
バージョン1.xと2.xがありますが、「Barba.js 使い方」などでググって出てくるものが大体1.xです。今回は公式以外にあまり情報がない2.xでの実装にチャレンジしてみようと思います。

インストール

何はともあれまずはyarnですね。

yarn add -D @barba/core

Yarn

https://yarnpkg.com/ja/

もっとサクッといきたいって方はcdnもあるみたいです。

<script src="https://unpkg.com/@barba/core"></script>

どちらの方法で読み込んでも問題無く動作します。

基本設定

ほとんど公式ドキュメントのまんまなのですが、英語で手順がわかりにくかったので僕のやった手順で進めていきます。

html

まずはhtmlの準備です。
DEMO1として以下のhtmlファイルを作ります。(htmlやbodyなど基本的な部分は省略)

<div data-barba="wrapper">
    <div data-barba="container" data-barba-namespace="demo-1">
     <a class="button" id="js-button" href="DEMO2へのリンク">GO TO DEMO2</a>
      <div class="bg" id="js-bg">
        <img src="背景画像">
      </div>
    </div>
</div>

ボタンと背景のみのシンプルなページを用意します。(CSSは省略)
ここでBarba.jsの設定として必要な部分は以下です。

  • data-barba="wrapper" :非同期遷移する箇所のラッパーを指定
  • data-barba="container":実際に遷移して入れ替わるソース部分
  • data-barba-namespace="demo-1":遷移する箇所に名前空間(ここではdemo-1)を指定。

data-barba-namespaceについては今回は使いませんでした。アニメーションを遷移する先ごとに毎回変えたいといった場合にこちらを指定しておけば細かく管理できそうです。

htmlはこれだけでOKです。

JS

次にJSを書いて、Barba.jsを使えるようにします。
webpackなどを利用している場合はJS内でimport。

import barba from '@barba/core'

cdnの場合は先ほどのタグを読み込みます。

<script src="https://unpkg.com/@barba/core"></script>

これでBarba.jsを使えるようになりました。

次に設定を書いていきます。

barba.init({
  transitions: [
  {
    async leave({ current, next, trigger }) {
      //ページを離れる時のアニメーション
      await leaveAnimation(current);
    },
    async afterLeave({ current, next, trigger }){
      //enter時の初期表示状態を設定
      $(next.container).find('#js-button').css('opacity', 0);
    },
    async beforeEnter({ current, next, trigger }) {
      //headタグの中身を入れ替え
      await replaceHeadTags(next);
    },
    enter({ current, next, trigger }) {
    //ページを表示する時のアニメーション
      enterAnimation(next);
    }
  }
  ]
});

内容を見ていきましょう。

barba.initでBarba.jsを呼び出します。
その際にoptionを指定できるのですが、今回はアニメーションを使った非同期遷移が目的ですので、使うのはtransitionオプションだけです。transitionオプションはページ遷移の際にいろんなタイミングで関数を実行できる便利なオプションです。

transitionオプションの種類は以下です。

  • beforeAppear:現在のページが表示される直前
  • appear:現在のページが表示される時
  • afterAppear:現在のページが表示された直後
  • before:最初
  • beforeLeave:現在のページを離れる直前
  • leave:現在のページを離れる時
  • afterLeave:現在のページを離れた直後
  • beforeEnter:次のページを表示する直前
  • enter:次のページを表示する時
  • afterEnter:次のページを表示した直後
  • after:最後

今回使ったのはleaveafterLeavebeforeEnterenterの4つです。

leave

まずページを離れる時のフックです。

async leave({ current }) {
   //ページを離れる時のアニメーション
   await leaveAnimation(current);
},

引数のcurrentに遷移前のページ情報が入っていますのでそれをアニメーションに利用します。
遷移をシームレスにしたいので、アニメーションが完全に終了してから次のtransitionを実行するためにasync/awaitを使います。(公式ドキュメントの方にPromiseでもできる方法が掲載してあります)

アニメーションの内容は以下です。anime.jsを使っています。

/*
* ページ離脱アニメーション
* @param {Object} current 離脱するページ(前のページ)の情報
* @return Promise
*/
function leaveAnimation(current) {
  const animation = anime.timeline()
  .add({
    easing           : 'easeOutSine',
    targets          : current.container.querySelector('#js-button'),
    duration         : 300,
    opacity          : [1, 0]
  })
  .add({
    easing           : 'easeInOutExpo',
    targets          : current.container.querySelector('#js-bg'),
    duration         : 600,
    opacity          : [1, 0],
    scale            : [1, 1.1]
  }, '-=300')
  ;
  return animation.finished;
}

ボタンをフェードアウトした後に背景をフェードアウトするアニメーションです。ポイントは戻り値をPromiseにすることです。これはanime.jsで簡単にできます。

anime.jsの基本的な使い方はこちら。バージョンは3.xを使っています。

anime.js

https://animejs.com/documentation/
enter

順番が前後しますが、アニメーションを先に設定しておきたいので次のページを表示する時のフックを見ていきます。

enter({ current, next, trigger }) {
  //ページを表示する時のアニメーション
  enterAnimation(next);
}

こちらはasync/awaitは付けません。
引数nextに遷移後のページ情報が入っているのでそちらをアニメーションします。アニメーションは先ほどのleaveAnimationの逆を設定します。

/*
* ページ表示アニメーション
* @param {Object} next 表示するページ(次のページ)の要素
* @return Promise
*/
function enterAnimation(next) {
  const animation = anime.timeline()
  .add({
    easing           : 'easeInSine',
    targets          : next.container.querySelector('#js-button'),
    duration         : 300,
    opacity          : [0, 1],
    translateY       : ['15px', 0]
  })
  .add({
    easing           : 'easeInOutExpo',
    targets          : next.container.querySelector('#js-bg'),
    duration         : 1000,
    opacity          : [0, 1],
    scale            : [1.1, 1]
  }, '-=300')
  ;
  return animation.finished;
}
afterLeave

次に現在のページを離れた直後のフックを設定します。こちらもasync/awaitは不要です。

afterLeave({ current, next, trigger }){
  //enter時の初期表示状態を設定
  $(next.container).find('#js-button').css('opacity', 0);
},

先ほどのleaveAnimationenterAnimationだけでは遷移が重なるタイミングで若干のチラつきが出てしまいます。そのため、チラつきの起きるボタンの部分に初期表示状態として事前にCSSを設定しておきます。

ここまででシームレスなアニメーションで遷移できるようになりました。

beforeEnter

こちらはアニメーションとは関係ありませんが、SEO対策です。
ページ遷移の際にdata-barba="container"を指定した要素の中身が変わりますが、SEOに必要なmetaタグなどはそのままでは変わりませんので、このフックで変更処理をはさみます。

beforeEnter({ current, next, trigger }) {
  //headタグの中身を入れ替え
  replaceHeadTags(next);
},

metaタグを入れ替える際に$.parseHTMLを使いたいのでjQueryを読み込んでおきます。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

jQueryが嫌いな人はがんばってネイティブで書きましょう。(今回はjQueryを使ったのでネイティブの記述は省略します)

/*
* <head>内のタグを入れ替える
* @param {Object} target 表示するページ(次のページ)の要素
*
*/
function replaceHeadTags(target) {
  const $newPageHead = $('<head />').html(
    $.parseHTML(
      target.html.match(/<head[^>]*>([\s\S.]*)<\/head>/i)[0],
      document,
      true
      )
    );
  const headTags = [
  "meta[name='robots']",
  "meta[name='keywords']",
  "meta[name='description']",
  "meta[property^='og']",
  "meta[name^='twitter']",
  "meta[itemprop]",
  "link[rel='next']",
  "link[rel='prev']",
  "link[rel='alternate']",
  "link[rel='canonical']",
  "script[type='application/ld+json']"
  ].join(',');
  // タグを削除
  $('head').find(headTags).remove();
  // タグを追加
  $newPageHead.find(headTags).appendTo('head');

  //Googleアナリティクスに送信
  if (typeof ga === 'function') {
    ga('send', 'pageview', location.pathname);
  }
}

metaタグを入れ替えるついでにGoogleアナリティクスへ情報を送っておけばPVも計測できます。

非同期遷移の場合は最初の1ページ目以外はアナリティクスへ送信する処理をJS内に書いておかないと正確な計測ができませんので注意です。

以上!ここまでで完成です!

完成

DEMO

画像とボタンだけの質素なページですが、簡単なアニメーションをかけて遷移するだけでちょっとリッチになりました。

追記

コンソールに出る文字列を消す方法

ライブラリをそのまま使うとコンソールに使っているプラグインのバージョンが勝手にログとして出てしまいます。

[@barba/prefetch]  2.1.5
[@barba/core]  2.3.12

これを消す方法はbarba.jsのLogger ClassからlogLevelを設定しなければならないようです。

import barba from '@barba/core'
import barbaPrefetch from '@barba/prefetch'

//prefetchのログを消すには使う前にログレベルを0に設定する
barba.Logger.setLevel(0);
barba.use(barbaPrefetch);

//coreのログを消すには初期化の際にオプションでログレベルを0に設定する
barba.init({
  logLevel : 0,
  ...
});

これで必要のないログは消せます。
ログについては以下を参考にしました。

公式ドキュメントのlogLevelの部分

公式ドキュメント Logger Class について

特定のリンクで非同期画面遷移したくない時

このブログもそうですが、目次などでページ内リンクを設定している場合にそのリンクもbarba.jsが反応してしまいます。

公式ドキュメントによると非同期遷移させない方法こちら。

import barba from '@barba/core';

barba.init({
  //ここに無効にする条件を書く
  prevent: ({ el }) => el.getAttribute('href').slice(0,1) === '#'
});

オプションのpreventがtrueの場合にbarba.jsを無効化します。
ここではページ内リンクを無効化したいので#が先頭にあるリンクである時と指定しました。これでhref="#target"のような指定がしてあるリンクは非同期遷移せずにページ内リンクとして動いてくれます。

もっと手軽な方法として以下も紹介されています。

<!-- htmlでリンクに直接属性を付けてリンクの非同期遷移を無効化 -->
<a href="#target" data-barba-prevent>ページ内リンク</a>

<!-- 親要素に属性をつけて子要素すべてのリンクの非同期遷移を無効化 -->
<div data-barba-prevent="all">
  <a href="#target1">ページ内リンク1</a>
  <a href="#target2">ページ内リンク2</a>
  <a href="#target3">ページ内リンク3</a>
</div>

data-barba-preventという属性をhtmlで直接要素に追記することで非同期遷移を無効化できます。条件ではなく特定のリンクを個別に無効化したいならこちらを利用するのが簡単そうです。また、data-barba-prevent="all"と親属性に付けることで全部まとめて無効化できるので、こちらは特定のエリアをまとめて無効化する場合に便利です。

公式ドキュメントのpreventの部分を参考にしました。

まとめ

今回はbarba.jsの使い方を簡単にまとめました。
慣れないとちょっとクセがあるかもしれませんが、それにしても簡単。
状態管理考えたり小難しい設計思想でわざわざSPAを作らなくてもいいですし、サイトにちょっと違いを出したい時にめっちゃ使えるのでとってもオススメです!ぜひ試してみてください!

記事一覧

Related

wordpress
inoue
inoue
TIPS

【WordPress】便利なアクションフック「template_redirect」

wordpress
inoue
inoue
TIPS

【WordPress】REST APIで独自エンドポイントの作り方

wordpress
inoue
inoue
TIPS

【WordPress】画像に自動付与されるsrcset属性を削除する

wordpress
inoue
inoue
TIPS

WordPressでよく使うプラグイン15選!

JavaScript
inoue
inoue
TIPS

スライダーといえばSwiper!

gulp+webpack
inoue
inoue
TIPS

gulp4 + webpack4でつくるフロント開発環境

ブログ記事一覧
  • HOME
  • TIPS
  • barba.js [v2]で簡単に非同期画面遷移を取り入れてページ高速化!