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
手順
以下のコマンドで起動
docker-compose up -d
取得したい画面の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 を渡しているのでセキュリティに注意する。未指定で実行する方法はわからなかった。