axeやLighthouseをEC2上で実行し結果をJSONで返すプログラムの作成

公開

axe-coreをEC2上で実行する

2月頃から複数ページの自動アクセシビリティ検証を実行し結果をCSVに保存する「axe-runner」の改良を進めてきましたが、HTTPでアクセスして結果を返してもらうことはできないか?というリクエストを頂きました。Node.jsの環境でPuppeteerを起動してaxe-coreを実行するという前提は変わらず、調査対象のURLを受信する仕組みと結果のJSONを送信する仕組みを構築すれば良いと考えました。

Node.jsでWebサーバーを構築できることは知っていたのですがそれほど詳しくもないので、オライリージャパンの「ハンズオンNode.js」を購入して情報収集をしました。結果、Expressを利用すると容易に実現できました。

const express = require('express');
const puppeteer = require('puppeteer');
const a11ycheck = require('./a11ycheck');
const app = express();
const port = 5001;
let browser;

app.get('/api/axe', async (req, res) => {
    const url = req.query.url;

    if (url) {
        const result = await a11ycheck(browser, url); // a11ycheckはaxe-runnerのコードを流用
        res.setHeader('Content-Type', 'application/json');
        res.send(JSON.stringify(result));
        return;
    }

    res.setHeader('Content-Type', 'application/json');
    res.send(
        JSON.stringify({
            message: 'Please specify the URL.'
        })
    );
});

app.listen(port, async () => {
    browser = await puppeteer.launch();
    console.log(`Example app running. Port ${port}.`);
});

EC2上にNode.jsをインストールし上記コードを実行すると、下記のようにaxe-coreの実行結果がレスポンスで返ってきました。
ブラウザでEC2にアクセスしアクセシビリティチェックの結果JSONが表示された画面のキャプチャ

なお、Puppeteerでキャプチャを取得し、EC2上でもページが正しく取得・描画されていることも確認しました。
EC2で実行しているPuppeteerで当ブログのページをキャプチャした

LighthouseをEC2上で実行する

別の作業をしている時、「Lighthouseもコマンドラインで実行できないだろうか?」とふと思いました。Googleで検索してみると「LighthouseをコマンドラインツールやNodeモジュールから利用してWebサイト表示速度計測 | フロントエンドBlog | ミツエーリンクス」の記事を見つけ、ProgrammaticallyにLighthouseを利用する方法を知りました。また、「Using Puppeteer with Lighthouse」の解説も見つけました。axe-coreを実行する部分をlighthouseに変更し、レスポンスのJSONを組み立てるだけで良さそうです。

プログラムを改良しEC2上で実行すると、下記のようにLighthouseの実行結果がレスポンスで返ってきました。
ブラウザでEC2にアクセスしLighthouseの結果JSONが表示された画面のキャプチャ

プロセスの永続化とマルチプロセス化

EC2上でプロセスの永続化をする方法を検討したのですが、購入した書籍を読むと「PM2」が人気のあるデプロイツールであることを知りました。PM2によりnpmでインストールしエコファイルシステムを記述してnpx pm2 startするだけでプロセスの永続化が実現できました。

同時にマルチプロセス化も容易に実現できました。プログラム内に記述するポート番号がプロセス毎に変わるようにし、forkモードで起動させ、nginxでリクエストを振り分けるように設定しました。nginxでリクエストを振り分けるのは初めてでしたが、以下のような記述でした。EC2はt3.microインスタンスでvCPUが2つなので、2プロセス起動します。

http {
    upstream nodejs {
        # ip_hash;
        server 127.0.0.1:5001 max_conns=1;
        server 127.0.0.1:5002 max_conns=1;
    }

    # Settings for a TLS enabled server.
    #
    server {
        listen       443 ssl http2 default_server;
        listen       [::]:443 ssl http2 default_server;
        server_name  _;

        location / {
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Forwarded-Host $host;
            proxy_set_header X-Forwarded-Server $host;
            proxy_pass http://nodejs;
        }
    }
}

むすび

このプログラムをさらに作り込むことで、サイト全体のアクセシビリティチェックやパフォーマンスチェックを実行する仕組みを構築することもできそうです。もし実現できれば、axe-runneを実行するためにパソコンにNode.jsの環境を準備したり、コマンドを打ち込む必要がなくなり、サイト全体のチェックが容易になると考えます。引き続き検討を続けていきたいと思います。