Web

Webページが読み込む CSS, JS コードから、実際に使われている部分のみを抽出する

投稿日:2021年4月16日 更新日:

1. Webページは無駄なコードを読み込んでいる

Webページは、読み込んでいる CSS や JavaScript のコードをすべて使用しているとは限りません

例えば Bootstrap (CSS) や jQuery (JavaScript) といった高機能なライブラリを利用する場合、それぞれ公式サイトから提供されているファイル(サイズも結構大きい)を読み込むわけですが、そのファイルに記述されているコードをフルに利用する、つまりそのライブラリの機能をフルに活用しているWebページというのはほとんどないのではないでしょうか。

つまり、その Webページは必要のないデータを読み込んでおり、その分だけページを表示するのに時間が掛かることになります。

本記事では、実際に使用している部分のコードだけを抽出する方法を紹介します。抽出したファイルを Webページに読み込ませることで Webパフォーマンスを向上させ、これが「ユーザーのフラストレーションを下げる」「PageSpeed Insights での得点を上げる」ことにつながります。

但し、Webページを最初に表示した時点で使用されているコードが抽出の対象となります。そのため、ページ上で何らかの操作を行うことによってそれ以外のコードが必要になる場合は、そのタイミングで元のファイルを読み込ませるといった対応も必要になります(PageSpeed Insights でのスコアを下げないために)。

2. 実際に使用されたコードを抽出する

JavaScript (Node.js) のライブラリである PuppeteerCoverage を利用します。Puppeteer というのは、Chrome や Chromium を利用することができるライブラリです。

目的の Webページの URL をパラメータとして指定し、下で紹介する JavaScript ファイルを実行すると、読み込んでいるファイル別に、使用されているコードのみを抽出したファイルが生成されます。但し、Chrome もしくは Chromium が利用できる GUI 環境でこのスクリプトファイルを実行する必要があります。この環境を用意するのが大変かもしれません。私は WSL 2 の Kali Linux で Win-KeX (kali-win-kex) を使う場合の注意点 で紹介した WSL 2 (Kali Linux) を利用しました。kali-win-kex というツールを使うことで、比較的容易に (Windows 上に) Linux の GUI 環境を用意することができます。Windows用の Node.js でも実行できるかもしれませんが、少し面倒なようです。

ターミナル上での操作は以下となります。

(事前に Node.js が使えるようにしておいてください。)

まず専用のディレクトリを作成してそちらに移動し、package.json ファイルを生成します。

$ mkdir foo
$ cd foo
$ npm ini

必要なライブラリをインストールします。

$ npm i puppeteer valid-url

次に、メインとなる JavaScript ファイルを生成しますが ファイル名は何でも構いません。ここでは、makeUsedFiles.js とします。このファイルの内容は以下のコードになっています。

const
  puppeteer = require('puppeteer'),
  fs = require('fs'),
  validUrl = require('valid-url');

(async () => {
  const browser = await puppeteer.launch(),
    page = await browser.newPage(),
    args = process.argv

  if (args.length <= 2) {
    console.error('Missing URL');
    process.exit(1);
  }

  const url = args[2];

  if (!validUrl.isUri(url)){
    console.log('NOT a valid URL');
    process.exit(2);
  }

  // Enable both JavaScript and CSS coverage
  await Promise.all([
    page.coverage.startJSCoverage(),
    page.coverage.startCSSCoverage()
  ]);
  // Navigate to page
  await page.goto(url);
  // Disable both JavaScript and CSS coverage
  const [jsCoverage, cssCoverage] = await Promise.all([
    page.coverage.stopJSCoverage(),
    page.coverage.stopCSSCoverage(),
  ]);

  const makeFile = (coverage, file_ext) => {
    let
      totalBytes = 0,
      usedBytes = 0,
      usedTextInEntry = '',
      count = 0,
      filename = '';

    console.log(`*.${file_ext} files:` + '\n');

    for (const entry of coverage) {
      usedTextInEntry = '';
      totalBytes += entry.text.length;
      for (const range of entry.ranges) {
        usedBytes += range.end - range.start - 1;
        usedTextInEntry += entry.text.slice(range.start , range.end) + '\n';
      }
      count++;
      filename = `${count}.${file_ext}`;
      console.log(`  (${count}) URL: '${entry.url}'`);
      fs.writeFileSync(filename, usedTextInEntry);
      console.log(`      File saved: '${filename}'` + '\n');
    }
    let bytesUsedRate = (usedBytes / totalBytes * 100);
    console.log(`  Bytes used: ${bytesUsedRate.toFixed(2)} %` + '\n');
  }

  makeFile(jsCoverage, 'js');
  makeFile(cssCoverage, 'css');
  process.exit(0)
})();
  • 指定された URL を Puppeteer に読み込ませています。
  • その際、予めカバレッジを計測するように指定しておきます。
  • カバレッジの計測結果(CSS, JS とで別)を受け取り、そこから「使用されている」コードを取得してまとめていき、最後にファイルとして保存しています。
  • Coverage で紹介されているコードを参考にしましたので、詳細はそちら等を参照してください。

あとは、この JavaScript ファイルを実行するだけです。引数として、目的の Webページの URLを指定して実行します。

$ node makeUsedFiles.js https://example.com

コマンドの結果は、「JavaScript の結果」と「CSSの結果」とに分かれて表示されます。

更に、「取得先のURL」と「そのURLから取得したコードから「使用されたコード」を抽出して保存したファイル名」が順番にリストアップされます。

実行結果
実行結果

今回は読み込み先毎に別ファイルが生成されるようにしましたが、JavaScript のコードを少し修正すれば、1つファイルにまとめて生成することもそれほど難しくありません。

3. おわりに

Webページに利用できるライブラリはたくさんありますが、それをそのまま読み込んでしまうと、必要のないコードが大量に含まれます。今回紹介した方法は少し面倒ですが、Webページのパフォーマンスを上げるには、今のところ便利だと思います。

Find Unused JavaScript And CSS With The Coverage Tab – Chrome Developers にあるように、Chrome の DevTools を使ってカバレッジを計測することもできます。しかし、こちらは「使用されている部分だけをま抽出する」といった機能はないようです。今後こちらにそういった機能が実装されるのではないかと予想(期待)しています。

📂-Web

執筆者:labo


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

Web

Chrome で SameSite=None に関する Cookieについての警告が表示される

Chrome で SameSite=None に関する Cookieについての警告が表示される理由について説明します。

Google

Google マップの地図をウェブページに埋め込む手順

Google マップの地図を、ウェブページに埋め込む手順について説明します。 手順自体は簡単なのですが、Google マップの仕様が時々変わり、操作手順もその影響を受けることがあるため、現時点(201 …

WordPress

【WordPress】JP Markdownプラグインが code タグの属性を削除する問題への対応方法

目次1. 現象2. 原因3. 対応方法 1. 現象 WordPress の JP Markdown プラグインを使っていると、以下のような (<pre> タグを伴わない単独の) <c …

SQLite

PHP + SQLite を利用してアクセスカウンターを作る

PHP + SQLite を利用してアクセスカウンターを作ります。

Chrome

ブロックされた Cookie を確認する方法 (Chrome の場合)

Chrome ブラウザにおいて、ブロックされた Cookie を確認する方法について説明します。