CSS Grid

Gridレイアウトは遅い

ブロックレイアウトで作成した8000行を超えるHTMLソースをほぼそのままGridレイアウトで書き直したところ、画面の表示速度が遅くなった。単純にPCの処理能力の問題なのか、構造的にレンダリングの負荷が大きすぎるのか、エンジンの最適化がまだ進んでいないのか、詳しくはわからないが、いずれにしてもそのままでは使えないレベルであった。

少し具体的に書くと、行事予定表を3ヶ月分表示するホームページで、変動要素の行事関連データはjavascriptでサーバーから一括して非同期通信で取得し、動的にHTMLに埋め込んでいる。データはいくつかの要素に分かれていて、中にはアイコンとして小さなイメージ情報も含まれている。1日のデータは、月、日、曜日、複数の時間区分、複数の行事データ、複数の行事アイコンなどで、平均的には1日あたり約10要素、3ヶ月で約900要素になる。さらに、個々のデータにはテーブルサーチや疑似要素による処理なども付加される。

それら約900個の情報をjavascriptで動的に書き込む度にリフロー(再描画)が発生する。結果としてスクリプトによる処理時間が100msをオーバーすることもあり、極端な場合は、400msなどというケースも発生する。Google Chromeのコンソールでチェックすると確実に時間オーバーの警告が出る。PCの性能やネットワークの能力、レンタルサーバーも水準以上の高性能な範囲であり、この状況ではページを閲覧する一般の利用者からみて不評となること間違いない。

自分がGridレイアウトを消化不良のまま非効率な使い方をしているのかもしれない。このページを書き直した後、時間の経過とともにGridレイアウトによって記述したページ数が増え、Auto機能を使ったシンプルなソースや、自動的な回り込み配置の機能を利用した効率的な記述など、使える技術の幅も広がってきた。現時点で再トライすれば少しは表示速度の高速化につながるのかもしれない。

だがしかし、そう思うようになったのは最近のことで、実は、"遅い"と感じた時点で、リフローの回数を減らす技術を模索し始め、最終的にHTMLをjavascriptで動的に生成する手法に取り組むこととした。

採用した手法はHTMLに対する修正を<html></html>の中で行うことなく、ローカルな環境である「fragmentNode」の中で行い、行事予定を組み込んで出来上がったオブジェクトをまとめて<html></html>の中に投入するという方法なのだが、行事がない、すなわちHTMLの段落ごと不要(あるいは非表示)というケースもあり、あらかじめ最大限のHTMLソースを用意しておいて不要な部分を非表示とするよりも、必要の都度HTMLソースを書き足していく方が合理的な処理となる。つまり、「修正」ではなくて必要なソースをその都度「生成」するという方法を採用した。結果、HTMLは外側の枠組みだけとなり、内容はすべてjavascriptで生成することとなった。

この手法によって、HTMLの行数は約8300行から300行へと1/27に激減した。動的な部分はjavascriptで生成するので当然といえば当然なのだが。そして肝心のChromeの警告は出なくなった。使用開始してまもなく6ヶ月が経過しようとしているが、今のところ、見た目に気づかれないような軽微な不具合が3件発生したのみで、致命的な不具合は発生していない。

javascriptは8本のソースで、全体で約2000行になった。プログラムの規模としては大きなものでないと思うが、HTMLによる繰り返し基調の視覚的に分かり易いソースコードから、配列を多用したいかにもプログラム風のソースコードになったため、パッと見には長文の行がぎっしりと並び、わけの分からないものに見える。 それを補うため、ドキュメントの量が多くなることを承知の上で、配列の説明や、最近はあまり見かけなくなったフローチャートを1ステップ対応で書くなど、根気よく見てもらえれば必ず理解できるという環境を整備してきた。

場違いを承知の上で、20代のときアセンブラー言語でプログラムを書いていた頃を思い出しながら、仕様を確実に書き落とし、机上で事前検証するやり方を実践してみた。ソースコードを書き始めてから完成するまでの期間は数日だった。全体としては間違いなく非効率的だが、時間がかかること以外は今に通用する手法であることを再認識した。非営利の取り組みにあっては50年前の昭和の技術もまだまだ使えることを実感した。

話を戻して、fgagmentNodeを使用して<html></html>の外でHTML文を組み立てたと書いたが、javascriptが扱うのは単なるテキストではなくて、htmlオブジェクトなので、HTMLを組み立てたというのが正しい。本来ならばレンダリングエンジンが担うべき役割の一部をわざわざjavascriptで複雑な仕組みを作って代行したということもできる。リフローの発生を抑止し、処理の高速化に寄与したということがその代償というわけだ。

このような処理は、本来、クライアントではなくてサーバーサイドでHTMLソースを編集する形で行う方が望ましいと思う。HTMLソースをHTMLというオブジェクトに仕上げるのはクライアント側のレンダリングエンジンの仕事であって、その役割分担を乱すことはやはり避けたいところだ。しかし、そのために必要な技術を持ち合わせないためにjavascriptを使うこととなった。自分の技術の限界でもある。