turbolinksで画面の表示をスピードアップ (1)

Laravelのフレームワークのおかげで、自分で作成した古いフレームワークもどきや、CodeIgniterの「もうサポートしません」(注1)フレームワークを脱出できて、以前よりしっかりした開発の領域に入ってきたと感じているこの頃。そして、ファサード、ネームスペース、クロージャ、トレイトなどを活用して、とてもモダン。しかし、最近人気が出てきたJavascriptのフレームワーク、Angular, React, Vuejsを使用したシングルページアプリ(SPA)がとても気になります。

Laravelのフレームワークのおかげで、自分で作成した古いフレームワークもどきや、CodeIgniterの「もうサポートしません」(注1)フレームワークを脱出できて、以前よりしっかりした開発の領域に入ってきたと感じているこの頃。そして、ファサード、ネームスペース、クロージャ、トレイトなどを活用して、とてもモダン。しかし、最近人気が出てきたJavascriptのフレームワーク、Angular, React, Vuejsを使用したシングルページアプリ(SPA)がとても気になります。

Laravelは基本的にサーバーサイドで、Angularなどはクライアントサイドなので、共存は可能と言えばそうなのだけれど、せっかく時間かけてマスターしたLaravelのプログラムを書き直すとか、今度はどのJavascriptフレームワークをマスターすればよいのとか、ajaxばかりでプログラム複雑になるのでは、とか、過去には、CodeIgniterで苦い目にあったし、最近やっと大きいプロジェクトを3年かけてLaravelに書き直したばかりなので、ちょっとポジティブにはなれません。

そんな中で、知り合ったのが題名のturbolinks。このテクノロジーの謳い文句は、

Javascriptのフレームワークを使用して複雑にすることなしに、シングルページアプリ(SPA)のパフォーマンスが得られる!

なんか「何もしなくても痩せる!」というダイエットサプリメントのような感じですが、今の私にピッタリ。とりあえず、紹介しましょう。

まず、メカニズムですが、そう難しくはありません。ページ内に同じサイト内のリンク、つまりがあると、turbolinksはajaxでそのページを取ってきてその中ののデータを現在のと取り換えます。は同じなので、結果的には、

のように、タブのところに表示される「ページロード中」のぐるぐるがなくなります。さらに、</code>やURLも正しく変わります。</p> <p>インストールはいたって簡単。</p> <p>以下の2つのファイルを用意してください。最初のファイルだけに、<code>turbolinks.js</code>が入っていることに注意してください。</p> <div class="code-filename">index.html</div> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-html" data-lang="html"><span style="display:flex;"><span><<span style="color:#f92672">html</span> <span style="color:#a6e22e">lang</span><span style="color:#f92672">=</span><span style="color:#e6db74">"ja"</span>> </span></span><span style="display:flex;"><span> <<span style="color:#f92672">head</span>> </span></span><span style="display:flex;"><span> <<span style="color:#f92672">meta</span> <span style="color:#a6e22e">charset</span><span style="color:#f92672">=</span><span style="color:#e6db74">"utf-8"</span>> </span></span><span style="display:flex;"><span> <<span style="color:#f92672">title</span>>Turbolinks</<span style="color:#f92672">title</span>> </span></span><span style="display:flex;"><span> <<span style="color:#f92672">script</span> <span style="color:#a6e22e">src</span><span style="color:#f92672">=</span><span style="color:#e6db74">"https://cdnjs.cloudflare.com/ajax/libs/turbolinks/5.0.3/turbolinks.js"</span>></<span style="color:#f92672">script</span>> </span></span><span style="display:flex;"><span> </<span style="color:#f92672">head</span>> </span></span><span style="display:flex;"><span> <<span style="color:#f92672">body</span>> </span></span><span style="display:flex;"><span> <<span style="color:#f92672">h1</span>>Turbolinks</<span style="color:#f92672">h1</span>> </span></span><span style="display:flex;"><span> <<span style="color:#f92672">ul</span>> </span></span><span style="display:flex;"><span> <<span style="color:#f92672">li</span>><<span style="color:#f92672">a</span> <span style="color:#a6e22e">href</span><span style="color:#f92672">=</span><span style="color:#e6db74">"page1.html"</span>>ページ 1</<span style="color:#f92672">a</span>></<span style="color:#f92672">li</span>> </span></span><span style="display:flex;"><span> </<span style="color:#f92672">ul</span>> </span></span><span style="display:flex;"><span> </<span style="color:#f92672">body</span>> </span></span><span style="display:flex;"><span></<span style="color:#f92672">html</span>> </span></span></code></pre></div><div class="code-filename">page1.html</div> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-html" data-lang="html"><span style="display:flex;"><span><<span style="color:#f92672">html</span> <span style="color:#a6e22e">lang</span><span style="color:#f92672">=</span><span style="color:#e6db74">"ja"</span>> </span></span><span style="display:flex;"><span> <<span style="color:#f92672">head</span>> </span></span><span style="display:flex;"><span> <<span style="color:#f92672">meta</span> <span style="color:#a6e22e">charset</span><span style="color:#f92672">=</span><span style="color:#e6db74">"utf-8"</span>> </span></span><span style="display:flex;"><span> <<span style="color:#f92672">title</span>>ページ 1</<span style="color:#f92672">title</span>> </span></span><span style="display:flex;"><span> </<span style="color:#f92672">head</span>> </span></span><span style="display:flex;"><span> <<span style="color:#f92672">body</span>> </span></span><span style="display:flex;"><span> <<span style="color:#f92672">h1</span>>ページ 1</<span style="color:#f92672">h1</span>> </span></span><span style="display:flex;"><span> <<span style="color:#f92672">p</span>><<span style="color:#f92672">a</span> <span style="color:#a6e22e">href</span><span style="color:#f92672">=</span><span style="color:#e6db74">"index.html"</span>>戻る</<span style="color:#f92672">a</span>></<span style="color:#f92672">p</span>> </span></span><span style="display:flex;"><span> </<span style="color:#f92672">body</span>> </span></span><span style="display:flex;"><span></<span style="color:#f92672">html</span>> </span></span></code></pre></div><p>これらのファイルをサーバーにアップして、「ページ1」や「戻る」リンクをクリックしてください。タブの部分において、もうロード中のぐるぐるは見えませんね。「すっ」とページが変わる感じです。また、URLやタイトルも正しく更新されています。</p> <p>しかし、ページ1においてブラウザの更新ボタンを押して画面を更新した後に、「戻る」のリンクをクリックするときは、ロード中のぐるぐるが見えます。これはpage1.htmlには、turbolinksがないからです。</p> <p>以下のデモでも体験できます。</p> <p><a href="https://larajapan.lotsofbytes.com/turbolinks/index.html" rel="noopener noreferrer" target="_blank"><a class="link" href="https://larajapan.lotsofbytes.com/turbolinks/index.html" target="_blank" rel="noopener" >https://larajapan.lotsofbytes.com/turbolinks/index.html</a></a></p> <p>ブラウザのインスペクトツールでも、ajaxが使用されていることがわかります。</p> <img src="inspec.png" alt="" width="759" height="216" class="alignnone size-full wp-image-2457" /> index.htmlのturbolinksをコールしている<code>script</code>の行を削除して違いも見てください。 <p>CDNではなく、turbolinksのファイルが欲しいなら、</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ wget https://github.com/turbolinks/turbolinks/archive/master.zip </span></span></code></pre></div><p>で取得可能です。unzipしてから、<code>dist/turbolinks.js</code>のファイルが取り出せます。</p> <p>知っておくこととして、</p> <p>ページの特定のリンクにおいてturbolinksを無効にしたいなら、<code>data-turbolinks=“false”</code>を入れてください。</p> <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>.. </span></span><span style="display:flex;"><span> <<span style="color:#f92672">body</span>> </span></span><span style="display:flex;"><span> <<span style="color:#f92672">h1</span>>Turbolinks</<span style="color:#f92672">h1</span>> </span></span><span style="display:flex;"><span> <<span style="color:#f92672">ul</span>> </span></span><span style="display:flex;"><span> <<span style="color:#f92672">li</span>><<span style="color:#f92672">a</span> <span style="color:#a6e22e">href</span><span style="color:#f92672">=</span><span style="color:#e6db74">"page1.html"</span> <span style="color:#a6e22e">data-turbolinks</span><span style="color:#f92672">=</span><span style="color:#e6db74">"false"</span>>ページ 1</<span style="color:#f92672">li</span>> </span></span><span style="display:flex;"><span> </<span style="color:#f92672">ul</span>> </span></span><span style="display:flex;"><span> </<span style="color:#f92672">body</span>> </span></span><span style="display:flex;"><span>.. </span></span></code></pre></div><p>クリック先のページを読み直したいときとかに必要です。私の経験では、ページを変更してセッションに値を入れるときには、これが必要でした。期待した動作にならないとか問題があるときに試してみること必要です。それから、<code>href</code>のリンクのクリックは<code>GET</code>のアクションとなりますが、<code>POST</code>のアクションには、turbolinksは関与しないので、フォームの投稿はスピードアップはしません。通常の画面の更新となります。</p> <p>実際のプロジェクトで使用となると、他にも知る必要なことがいくつか(たくさんではない)あります。例えば、Google Analyticsは正しく反映されるのか、とか、Wordpressでも使用できるかとか。知識を整理して、将来により情報を共有します。</p> <h2>注1</h2> <p>CodeIgniterは私が初めて使用したPHP言語のフレームワークです。どこかのサイトで紹介されていて簡単そうなので使い始めました。日本語のデータ処理に問題があったので使える部分はほとんどコントローラの部分だけでしたが、いくつかのお客さんのプロジェクトの開発に使いました。当時は一番人気のフレームワークでしたが、その絶頂期の2013年にCodeIgniterを開発した会社がリソースがないことを理由に開発を辞める宣言をしました。そこで開発が止まり1年後にはカナダの専門学校がメンテナーとなり現在はそこでオープンソースとして管理されています。</p> <p>ということで、CodeIgniterはまったく消え去ったわけではありませんが、Laravelを使い始めて振り返ると、CodeIgniter自体のフレームワークはその時点ですでに古く、現在のPHP言語のネームスペースに基づくcomposerのパッケージを基本として作成されたものでもなく、より複雑になるウェブアプリの開発にはそのままでは不可能です。</p> </section> <footer class="article-footer"> <section class="article-tags"> <a href="/tags/spa/">SPA</a> </section> </footer> </article> <footer class="site-footer"> <section class="copyright"> © 2026 ララジャパン </section> <section class="powerby"> <a href="https://gohugo.io/" target="_blank" rel="noopener">Hugo</a> で構築されています。 <br /> テーマ <b><a href="https://github.com/CaiJimmy/hugo-theme-stack" target="_blank" rel="noopener" data-version="3.34.2">Stack</a></b> は <a href="https://jimmycai.com" target="_blank" rel="noopener">Jimmy</a> によって設計されています。 </section> </footer> <div class="pswp" tabindex="-1" role="dialog" aria-hidden="true"> <div class="pswp__bg"></div> <div class="pswp__scroll-wrap"> <div class="pswp__container"> <div class="pswp__item"></div> <div class="pswp__item"></div> <div class="pswp__item"></div> </div> <div class="pswp__ui pswp__ui--hidden"> <div class="pswp__top-bar"> <div class="pswp__counter"></div> <button class="pswp__button pswp__button--close" title="Close (Esc)"></button> <button class="pswp__button pswp__button--share" title="Share"></button> <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button> <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button> <div class="pswp__preloader"> <div class="pswp__preloader__icn"> <div class="pswp__preloader__cut"> <div class="pswp__preloader__donut"></div> </div> </div> </div> </div> <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap"> <div class="pswp__share-tooltip"></div> </div> <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)"> </button> <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)"> </button> <div class="pswp__caption"> <div class="pswp__caption__center"></div> </div> </div> </div> </div><script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.js"integrity="sha256-ePwmChbbvXbsO02lbM3HoHbSHTHFAeChekF1xKJdleo="crossorigin="anonymous" defer > </script><script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe-ui-default.min.js"integrity="sha256-UKkzOn/w1mBxRmLLGrSeyB4e1xbrp4xylgAWb3M42pU="crossorigin="anonymous" defer > </script><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/default-skin/default-skin.min.css"crossorigin="anonymous" ><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.css"crossorigin="anonymous" > </main> </div> <script src="https://cdn.jsdelivr.net/npm/node-vibrant@3.1.6/dist/vibrant.min.js"integrity="sha256-awcR2jno4kI5X0zL8ex0vi2z+KMkF24hUW8WePSA9HM="crossorigin="anonymous" > </script><script type="text/javascript" src="/ts/main.c922af694cc257bf1ecc41c0dd7b0430f9114ec280ccf67cd2c6ad55f5316c4e.js" defer></script> <script> (function () { const customFont = document.createElement('link'); customFont.href = "https://fonts.googleapis.com/css2?family=Lato:wght@300;400;700&display=swap"; customFont.type = "text/css"; customFont.rel = "stylesheet"; document.head.appendChild(customFont); }()); </script> </body> </html>