皆さんこんにちは。エンジニアの中井です。
先日弊社で 持続可能なWeb開発 をテーマとし、プロジェクト脱 jQuery を進めました。
その際に得た知見についてご共有させていただきます。

はじめに

そもそもなぜ脱 jQuery なのか

jQueryが広く使用されていた時期、2006年から2010年代初頭まで、さまざまなブラウザの非互換性や標準化の不足などに悩まされていました。その中でjQueryは、異なるブラウザで一貫性のある動作を提供し、DOMの簡略化やイベントハンドリングの容易化など、開発者にとって多くの利点をもたらしました。

しかし、次第にWeb技術やブラウザの標準化が進むにつれて、jQueryを使用するメリットが減少しました。

  • モダンなブラウザの標準化
    • 現代のブラウザは、異なるベンダーによる標準化の進展により、jQueryを使用しなくてもクロスブラウザの開発が容易になりました。これにより、ネイティブなJavaScriptとDOM APIを使用することで、同じ目的を達成できるようになりました。
  • 高速なJavaScriptエンジンの登場
    • ブラウザのJavaScriptエンジン(例: V8、SpiderMonkey)の高速化により、ネイティブのJavaScriptコードが非常に効率的に実行されるようになりました。
  • ライブラリ、フレームワークの普及
    • フロントエンド開発ではモジュール性が強調され、React、Vue.js、Angular などのモダンなライブラリ、フレームワークが普及しました。これらは、コンポーネントベースのアーキテクチャを提供し、構造化した管理が可能となりました。

jQueryを使用する必要性が低下したこと等から、ネイティブの JS やモダンなライブラリに移行していく流れとなりました。

また、Drupal においても jQuery から徐々に離れる動きがあります。(参照: Replace JQuery with vanilla Javascript in core)

jQueryの代替手段の概要

jQuery の代替手段の選定は、効率的な開発と軽量化を追求する中で行われました。
以下は、選定した技術とその目的です。

Vanilla JS

Vanilla JSの選定は、外部ライブラリに頼らずネイティブな JavaScript でも、問題なく開発できるかどうかの検証を兼ねて選定しました。
また、外部ライブラリを介さずに機能を実現することで、言語自体の特性やブラウザの動作に対する理解を深め、個々のコーディングスキルの向上を期待しています。

Alpine.js

Alpine.js はTwigとの相性の検証、可読性の向上を目的として採用しました。
こちらは長くなりそうなので詳細については別途記事を作成したいと思います。

脱 jQuery 手順

1. jQuery 依存となっているかの確認方法

Drupal では jQuery 等のライブラリを使うとき、*.libraries.yml に依存関係として記載する必要があります。 そのため、各カスタムモジュール、カスタムテーマディレクトリにある*.libraries.ymldependencies を確認することで依存関係にあるかどうかを確認できます。
以下は apex に jQuery が依存関係として定義されている例です。

apex:
  js:
    js/legends.js: {}
  dependencies:
    - core/drupal
    - core/once
    - core/jquery

2. libraries.yml から依存を削除

core/jquery を削除します。

apex:
  js:
    js/legends.js: {}
  dependencies:
    - core/drupal
    - core/once

3. JSファイルのコードを修正

jQuery に依存していたコードを Vanilla JS に置き換えます。
ここは Drupal に限らず一般的な手法になると思います。

以下はテーブルにクラスを付与し、テーブルをラップする div タグを追加する例です。

  • Before:
(($, Drupal, once) => {
  Drupal.behaviors.legendsTable = {
    attach: context => {
      $(once('legends-table', 'table', context))
        .addClass('legends-table__table');
        .wrap('<div class="legends-table" />')
    },
  };
})(jQuery, Drupal, once);
  • After:
((Drupal, once) => {
  Drupal.behaviors.legendsTable = {
    attach: context => {
      once('legends-table', 'table', context).forEach(element => {
        const wrapper = document.createElement('div');
        wrapper.className = 'legends-table';
        element.parentNode.insertBefore(wrapper, element);
        wrapper.appendChild(element);
        element.classList.add('legends-table__table');
      });
    },
  };
})(Drupal, once);

変更箇所としては以下の通りです。

  • 即時関数の引数のjQueryに関する記載を削除
    • ((Drupal, once) => {})(Drupal, once) に変更し、jQueryの引数と関連する部分を削除しました。
  • jQuery オブジェクトから DOM API に切り替え
    • $(once('legends-table', 'table', context))once('legends-table', 'table', context).forEach(element => {}) に変更し、各テーブル要素に対してVanilla JSを使用して操作するようにしました。
    • また、上記の変更に伴い、 jQueryの addClass と wrap メソッドも DOM API を使った実装に変更しました。

パフォーマンス

jQuery は Drupal コアで使用されており、jQuery のダウンロード時間においては差異はありません。ですので今回はテーブルを1000個作成し処理速度の測定を行いました。

jQuery Vanilla JS
時間 382ms 153ms

今回の処理では、処理時間が1/2以下に短縮されるといった結果になりました。

まとめ

「脱jQuery」プロジェクトを進める中で、jQuery が従来のWeb開発に果たしてきた役割を再評価する機会となりました。以前は開発の効率化やクロスブラウザの実装を容易にするライブラリとして、jQuery に頼ることが一般的でした。

しかし、Web技術の進化や標準化により、jQueryなしでも十分な実装が可能になり、コストの面でもjQueryを必ずしも導入する必要性が低くなってきています。ウミでも今後は jQuery に頼らず、Vanilla JS ( + モダンJSライブラリ )で実装していく方針となりました。

個人的に、Drupal とモダンな JSライブラリを組み合わせが、かなりイケてるのではと妄想しているので、その理由については別途記事を作成し、掘り下げていきたいと思います。

以上で終わります。ありがとうございました!

参照


共に働く新しい仲間を
募集しています

スタジオ・ウミは「Drupal」に特化したサービスを提供する Drupal のエキスパートチーム。
フルリモート&フレックス制だから、働く場所を選ばず時間の使い方も自由です。
そんなワークライフバランスの整った環境で、当ブログに書かれているような
様々な技術を共に学びながら、Drupalサイト開発に携わってみたい方を募集しています。
まずはお話だけでも大歓迎!ぜひお気軽にご連絡ください。