SPAのようなJSで画面構築してレンダリングされた後のHTMLを取得したいので調査

以下の条件で検討した。

  • ReactやVueなどJSフレームワークに依存しない

方法

最初はPuppeteerやPlaywrightを使用する方法を考えたが、調べていくうちに Prerender という存在を知り使ってみた。

PrerenderにはChromeが必要なため、インストールしたイメージを用意した。

ディレクトリ構造
.
├── Dockerfile
└── docker-compose.yml

サーバとして起動するだけなためEntrypointにJSを直接記述している。

Dockerfile
FROM node:bullseye-slim
## 1. Chromeのインストール
### 1. 準備
RUN apt update -y && \
    apt install -y curl gpg && \
    mkdir -p /usr/local/share/keyrings/
### 2. インストール
    # リポジトリキーを取得し一旦インポート
RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | gpg --no-default-keyring --keyring /tmp/temp-keyring.gpg --import && \
    # リポジトリキーをバイナリ形式でエクスポート
    gpg --no-default-keyring --keyring /tmp/temp-keyring.gpg --export --output /usr/local/share/keyrings/chrome.gpg && \
    # リポジトリキーを指定してリポジトリを登録
    sh -c 'echo "deb [arch=amd64 signed-by=/usr/local/share/keyrings/chrome.gpg] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' && \
    # インストール
    apt update -y && \
    apt install -y google-chrome-stable
## Prerenderをグローバルインストール
ENV NODE_PATH /usr/local/lib/node_modules
RUN npm i -g prerender
## Node.jsの引数としてJSを渡しサーバーを起動
ENTRYPOINT [ "node", "-e", "require('prerender')({chromeFlags: ['--no-sandbox','--headless','--disable-gpu','--remote-debugging-port=9222','--hide-scrollbars',],}).start();"]
docker-compose.yml
version: "3"

services:
  prerender:
    build: ./
    ports:
      - 3000:3000

手順

  1. 以下のコマンドで起動

    • docker-compose up -d

  2. 取得したい画面のURLを http://localhost:3000/render?url= の後にパラメータとしてつなげてGET(ここではTODOMVCでやってみた)

curl https://todomvc.com/examples/react/#/ 実行時の一部のNode
	<section class="todoapp"></section>
	<section class="todoapp">
		<div data-reactid=".0">
			<header class="header" data-reactid=".0.0">
				<h1 data-reactid=".0.0.0">todos</h1><input class="new-todo" placeholder="What needs to be done?"
					value="" data-reactid=".0.0.1">
			</header>
		</div>
	</section>

注意点

オプションに --no-sandbox を渡しているのでセキュリティに注意する。未指定で実行する方法はわからなかった。