PHPでもNextしたい

2021/07/14に公開約3,900字

したかったので開発しました!

https://quocca-works.com/accela/

ドキュメントはサイト内にあるので、この記事ではNext.jsとの対比や簡単なコードで、Accelaの特徴を紹介していきます。実際にどういった動作をするかは当サイトで確認することができ、サイトのデータ自体もダウンロードできるので、サンプルとしてお使いください。

Next.jsを参考にした機能

Next.js(React)の設計思想やNode.jsのエコシステムは素晴らしいものですが、Accelaはその全てを参考にして作っているわけではありません。主に以下の3点を踏襲した上で、別のコンセプトを盛り込んで開発しています。(逆に言うと、それ以外の特徴は当てはまらないものが多いです。)

  1. クライアントサイドでの高速なページ移動、DOM構築
  2. テンプレートとルーティングの対応、動的ルーティング
  3. 静的ビルド (Static Site Generation)

特に1が簡単にできるツールが欲しかった、というのが開発の動機の一つです。

コンセプト

AccelaはNext.jsの代替を目指している訳ではなく、今のところは小規模なサイト開発に的を絞っています。また、PHPとjQueryでできているので、導入するまでのコストも最小限で済みます。

私の周りの環境の話ですが、結構まだまだWordPress、PHP+レンタルサーバ、jQueryでの開発など、枯れた技術を扱うことが主流です。たとえばReactやVueなどのモダンな技術を提案するにしても、運用・保守を考えて見送られるケースも往々にしてある訳ですね。

そういった状況もあり、設計思想というほどではないですが、以下を意識して開発しています。

  • 動作要件のゆるさ (レンタルサーバでもどこでも動く)
  • 学習コストの低さ (ほぼHTMLの知識のみである程度開発可能)
  • jQueryを使った機能拡張

jQueryは本当はプロトタイプ開発に使うだけの予定でしたが、そのまま残してあります。ちなみに、たぶんAccelaの全機能の半分くらいがjQueryベースです。今後リプレースする可能性もありますが、学習コストを下げる意味でも現時点では悪くない選択だと思っています。

はじめ方

Download Accela

サイトのダウンロードページに置いてあるzipファイルには、Accelaのサイト自身もサンプルとして同梱されているので、そのまま確認することができます。

DockerやApacheのVirtualHostを使って、ドキュメントルートに配置してください。特に設定ファイルなどはありません。サブディレクトリでの動作は未検証です。

仕様の簡単な説明

上で示したクライアントサイドでの高速なページ移動、DOM構築については、自動的に全てのページに適用されます。通常のaタグにページ移動のイベントが登録されるので、開発時には特に意識する必要はありません。
ページ遷移時のアニメーション(フェードなど)を追加したい場合も、後述するフックを使えば簡単に実装できます。

ページテンプレートとルーティング

app/pages/index.htmlにファイルを作るだけで、自動でルーティングにGET /が追加され、ページを表示することができます。テンプレートの内容は、たとえば以下のような簡略化されたHTMLを記述するだけです。<body />の中身はそのままコンテンツになります。

app/pages/index.html
<head>
  <title>ページタイトル</title>
</head>

<body>
  <header>
    <h1>ページタイトル</h1>
    <p>トップページです。</p>
  </header>

  <main>
    <p>コンテンツ</p>
    ...
  </main>
</body>

テンプレートは以下のようにURLにマッピングされ、末尾のスラッシュの有無は区別されます。

テンプレート URL
app/pages/index.html /
app/pages/about.html /about
app/pages/about/index.html /about/
app/pages/about/accela.html /about/accela
app/pages/news/[id].html /news/1, /news/2, ...

共通の<head />

メタ情報やCSSの読み込みなど、共通の情報はまとめてapp/common.htmlに記述すると、自動的に全てのページに出力されます。

app/common.html
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <link rel="preconnect" href="https://fonts.gstatic.com">
  <link rel="stylesheet" href="/assets/css/style.css">
</head>

ページ移動のフック

内部リンクをクリックした時にJavaScriptでページ移動が行われますが、その移動処理をフックすることでページ遷移アニメーションを追加することができます。

app/script.js
ACCELA.move_page = function(page_content, move){
  $("#accela").fadeOut(200, function(){
    move();
    $("#accela").fadeIn(400);
  })
};
$("#accela")

Accela内部で扱うDOMのルートで、コンテンツは全てこの中に含まれます。
(Next.jsの<div id="__next" />相当。)

move()

実際にコンテンツを書き換える処理の関数で、以下を行います。

  • headの差分書き換え
  • bodyの書き換え
  • URLの書き換え(pushState)

move_pageの中では、必ず1回この関数を実行する必要があります。

fadeOut, fadeIn

jQueryでアニメーションを実行していますが、もちろんCSSアニメーションで実装しても問題ありません。

その他、トラッキングの追加やアクセス解析系もこのフックで実行することができます。

app/script.js
ACCELA.move_page = function(page_content, move){
  move();
  gtag('config', 'G-0000000000', {'page_path' : location.pathname});
};

マークダウン

組み込みでマークダウンのパーズに対応しているので、CMSと連携してドキュメントを含むサイトの構築にも使うことができます。

https://quocca-works.com/accela/doc/built-in-modules/

共通コンポーネント、動的なコンテンツ

サーバサイド・クライアントサイドどちらでも処理を追加できるように、いくつかの機能を用意しています。詳しくはAccela Documentを参照してください。

  • サーバコンポーネント (PHPで処理を記述)
  • コンポーネント (HTMLを記述)
  • 値のバインディング (HTMLタグにdata-*プロパティを記述)
  • モジュール (JavaScriptで処理を記述)

静的ビルド

全てのデータを、HTML/JS/JSONとして書き出すことができます。諸々機能追加予定ですが、現時点でも問題なく動作します。

⚠️ 注意点

現在のAccelaは、最初のページアクセスで全てのページのデータをまとめて取得する仕組みなので、ページ数の多い大規模なサイトの構築には向いていません。分割する仕組みなどは構想中ですが、あくまで小規模サイトの開発に照準を合わせた仕様になっています。


以上簡単な説明ですが、特殊な文法も存在せず、基本的にはHTMLを書くだけで、Next.jsのような超高速・UXを意識したサイトを作ることができます。まだエラー処理やデバッグが甘かったり、ビルド機能も貧弱なので、まずはプロダクションレベルで使えるものを目指します。

質問やバグ報告もお待ちしてます。

Discussion

ログインするとコメントできます