1. Webページは無駄なコードを読み込んでいる
Webページは、読み込んでいる CSS や JavaScript のコードをすべて使用しているとは限りません。
例えば Bootstrap (CSS) や jQuery (JavaScript) といった高機能なライブラリを利用する場合、それぞれ公式サイトから提供されているファイル(サイズも結構大きい)を読み込むわけですが、そのファイルに記述されているコードをフルに利用する、つまりそのライブラリの機能をフルに活用しているWebページというのはほとんどないのではないでしょうか。
つまり、その Webページは必要のないデータを読み込んでおり、その分だけページを表示するのに時間が掛かることになります。
本記事では、実際に使用している部分のコードだけを抽出する方法を紹介します。抽出したファイルを Webページに読み込ませることで Webパフォーマンスを向上させ、これが「ユーザーのフラストレーションを下げる」「PageSpeed Insights での得点を上げる」ことにつながります。
但し、Webページを最初に表示した時点で使用されているコードが抽出の対象となります。そのため、ページ上で何らかの操作を行うことによってそれ以外のコードが必要になる場合は、そのタイミングで元のファイルを読み込ませるといった対応も必要になります(PageSpeed Insights でのスコアを下げないために)。
2. 実際に使用されたコードを抽出する
JavaScript (Node.js) のライブラリである Puppeteer の Coverage を利用します。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 を使ってカバレッジを計測することもできます。しかし、こちらは「使用されている部分だけをま抽出する」といった機能はないようです。今後こちらにそういった機能が実装されるのではないかと予想(期待)しています。