はじめに
「よっしゃあ、サイト高速化するぞ!」
「むむ、CSSサイズが大きいなぁ。軽量化しよう!」
「このCSS使われてないやん、、削除ー!」
・・・・・
他のページのレイアウト崩れてるやん 😇
CSSの構造が複雑になっていたので、削除の影響範囲わかんない。どうしよう。
ってことで、対応の前後でレイアウト崩れがないかどうかをチェックできるスクリプトをつくりました。
あんましnode使ったことなかったんですが、puppeteerでさくっと作れました。
流れとしては、
- 対応の前後でサイトのスクショを撮る
- スクショ画像の差分をチェックする
っていう手順です。
サイトのスクショを撮る
PATHS
にスクショ撮影対象のパスを入れてます。
スマホサイトにするためにUserAgentも設定。
ディレクトリつくってそこに一括で画像保存してます。
const DEFAULT_VIEWPORT = {
width: 375,
height: 812,
deviceScaleFactor: 1,
};
const puppeteer = require('puppeteer');
const fs = require('fs');
const DEFAULT_HOST = 'https://qiita.com';
const PATHS = [
'/',
'/paranishian',
'/tags/aws',
'/tags/ruby'
]
const date = new Date();
const timestamp = date.getTime().toString();
async function run(){
const browser = await puppeteer.launch({
defaultViewport: DEFAULT_VIEWPORT,
});
const context = await browser.createIncognitoBrowserContext();
const page = await context.newPage();
await page.setUserAgent('Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)')
fs.mkdirSync(timestamp);
for(const path of PATHS) {
const url = DEFAULT_HOST + path;
await page.goto(url, {waitUntil: 'networkidle2'});
console.log(`Done! : ${url}`);
const filename = path.replace(/\//g, '_') + '.png';
await page.screenshot({path: timestamp + '/' + filename, fullPage: true})
}
await browser.close()
}
run()
さっそく実行。
❯ node main
Done! : https://qiita.com/
Done! : https://qiita.com/paranishian
Done! : https://qiita.com/tags/aws
Done! : https://qiita.com/tags/ruby
❯ ls -l 1542803191786
total 12144
-rw-r--r-- 1 paranishian www 657027 11 21 21:26 _.png
-rw-r--r-- 1 paranishian www 749702 11 21 21:26 _paranishian.png
-rw-r--r-- 1 paranishian www 2202719 11 21 21:26 _tags_aws.png
-rw-r--r-- 1 paranishian www 2599285 11 21 21:26 _tags_ruby.png
こんな感じで画像保存してます。
差分をチェックする
pixel-diff
で差分をチェックします。
const DIFF_DIRECTORY = 'diff';
const fs = require('fs');
const PixelDiff = require('pixel-diff');
const PNG = require('pngjs').PNG;
const path = require('path');
const argv = require('yargs')
.options({
'a': {
describe: '比較対象画像のディレクトリA',
type: 'string',
demandOption: true
},
'b': {
describe: '比較対象画像のディレクトリB',
type: 'string',
demandOption: true
},
})
.help()
.argv;
async function checkDiff(filename) {
const imageA = `${argv.a}/${filename}`;
const imageB = `${argv.b}/${filename}`;
const pngA = await PNG.sync.read(fs.readFileSync(imageA));
const diff = new PixelDiff({
imageAPath: imageA,
imageBPath: imageB,
thresholdType: PixelDiff.THRESHOLD_PERCENT,
threshold: 0.01,
imageOutputPath: `${DIFF_DIRECTORY}/${filename}`,
cropImageB: {
x: 0,
y: 0,
width: pngA.width,
height: pngA.height,
},
});
const result = await diff.runWithPromise();
console.log(`Found ${result.differences} pixels differences in ${filename}.`);
}
async function run(){
if (!fs.existsSync(DIFF_DIRECTORY)){
fs.mkdirSync(DIFF_DIRECTORY);
}
if (!fs.existsSync(argv.a) || !fs.existsSync(argv.b)){
throw new Error('ディレクトリが見つかりません!');
}
fs.readdir(argv.a, (err, files) => {
files.forEach(file => {
if(path.extname(file) != '.png') {
return;
}
checkDiff(file)
});
})
}
run()
引数に対象ディレクトリ名を指定して実行すると、diffディレクトリが作成されて差分画像が保存されます。
❯ node diff -a 12345 -b 67890
...
最終的にはCIに導入してmasterとの差分チェックを自動化するのが目標です。
それにしてもpuppeteerは簡単で最高ですね 🤤
どなたかの参考になれば幸いです 🤗
参考