https://github.com/kazuma1989/headless-chrome-cloud9-handson
Try Headless Chrome (with Puppeteer) on AWS Cloud9 (EC2 Amazon Linux).
https://github.com/kazuma1989/headless-chrome-cloud9-handson
Last synced: 3 months ago
JSON representation
Try Headless Chrome (with Puppeteer) on AWS Cloud9 (EC2 Amazon Linux).
- Host: GitHub
- URL: https://github.com/kazuma1989/headless-chrome-cloud9-handson
- Owner: kazuma1989
- License: mit
- Created: 2018-02-24T02:06:58.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2018-02-24T13:31:30.000Z (over 7 years ago)
- Last Synced: 2025-01-22T09:33:06.691Z (5 months ago)
- Language: Shell
- Size: 258 KB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Headless Chrome on Cloud9 ハンズオン
[AWS Cloud9](https://aws.amazon.com/cloud9/) 上で [Headless Chrome](https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md) を使ってみるハンズオンです。
**Cloud9** は、ブラウザーのみでコードを記述、実行、デバッグできるクラウドベースの統合開発環境 (IDE) です。
クラウド上の Linux インスタンスをブラウザーから覗くというスタイルなので、ローカルマシンへのインストールは一切不要です。**Headless Chrome** は、GUI を必要としない Chrome ブラウザーです。
GUI のない(まさに Cloud9 インスタンスのような)Linux 上でも簡単に実行でき、ブラウザー操作を自動化するのに役立ちます。対象読者は以下のとおりです:
- Headless Chrome を使ったことがない人
- Cloud9 を使ったことがない人
- どちらも使ったことはあるが、組み合わせて使ったことはない人[Angular](https://angular.io/) や [React](https://reactjs.org/) といったフレームワークは使わないので HTML, JavaScript が少しでも書けるなら大丈夫です。
## Cloud9 セットアップ
### Why Cloud9?
他のクラウド IDE には、たとえば [Codeanywhere](https://codeanywhere.com/) があります。
クラウド IDE の中から Cloud9 を選択したのは、Codeanywhere が劣っているからではなく、既に持っていた AWS アカウントによって Cloud9 を簡単に利用できたからです。必要なのは AWS EC2 の利用料のみで、EC2 の知識があれば VPC 内の他のサーバーと連携することも可能という柔軟性を持ち、とにかくハードルが低いのがよいですね。
### Create environment
AWS console にログインし Cloud9 のページを開きます。
Cloud9 は東京リージョンでは使えないので、`Asia Pacific (Singapore)` を選択します。Cloud9 のページで `Create environment` を選択します。
Name は、ファイル名をつける感覚で、好きなものを設定すればよいです。
Environment settings は、デフォルト (`EC2`, `t2.micro`, `After 30 minutes`) のまま、`Create environment` を選択します。数分待てばインスタンスが起動し、セットアップは完了です。
簡単!コードを書くまえに [Git セットアップ (optional)](docs/git-setup.md) をおすすめします。
## Web アプリケーションの作成
サンプルは [kazuma1989/headless-chrome-cloud9-handson: Try Headless Chrome (with Puppeteer) on AWS Cloud9 (EC2 Amazon Linux).](https://github.com/kazuma1989/headless-chrome-cloud9-handson) にあります。
### Node.js プロジェクトの初期化
サーバーを起動したり、Headless Chrome を操作したりするため、[Node.js](https://nodejs.org/en/) を使います。
まず、Cloud9 にデフォルトでインストールされている Node.js のバージョン (v6.12.3) をアップグレードします:```bash
nvm install 8.9.4
nvm alias default v8.9.4
```次に、自分のプロジェクトフォルダーを作成し、Node.js プロジェクトとして初期化します:
```bash
cd ~/environment/
mkdir myapp
cd myapp
npm init -y
````package.json` が生成されたら成功です:
```diff
+ myapp/
+ └── package.json
```### index.html 作成
index.html を追加します。
Headless Chrome の動作を確認しやすくするため、最低限のスタイルとスクリプトを追加しています:```diff
myapp/
+ ├── index.html
└── package.json
```index.html
```html
My App
html {
background: gainsboro;
border: solid 1px black;
box-sizing: border-box;
color: red;
height: 100%;
}const date = new Date().toLocaleString('ja-JP-u-ca-japanese', {
year: 'numeric',
month: 'short',
day: 'numeric',
weekday: 'short',
});document.querySelector('main').textContent = date;
```
### http-server インストール
index.html を見る web サーバーとして `http-server` をインストールします:
```bash
npm install --save-dev http-server
``````diff
myapp/
├── index.html
+ ├── node_modules
├── package.json
+ └── package-lock.json
```package.json には `start` スクリプトを追加し、`npm run start` によってサーバーが起動するようにしておきます:
```diff
"scripts": {
+ "start": "http-server ./",
"test": "echo \"Error: no test specified\" && exit 1"
},
````npm run start` によってサーバーを起動したら、Cloud9 メニュー > Preview > Preview Running Application を選択して、アプリケーションを表示します。
以下のような画面が表示されれば成功です:
🎉
## Headless Chrome によるテスト作成
### Why Headless Chrome? Puppeteer?
他のヘッドレスブラウザーには、たとえば [PhantomJS](http://phantomjs.org/) や [Nightmare](http://www.nightmarejs.org/) があります。
これらは独自のエンジンや [Electron](https://electronjs.org/) ベースのエンジン、すなわち Chrome とは異なったエンジンで動作するのに対し、Headless Chrome は Chrome 本体の起動モードの一つです。
とくに理由がなければ、ユーザーが使う「本物」でテストできるほうが好ましいでしょう。[Puppeteer](https://github.com/GoogleChrome/puppeteer) は、Headless Chrome の Node.js API です。
同様のライブラリーにたとえば [Chromeless](https://github.com/graphcool/chromeless) がありますが、Puppeteer は Chrome 開発チーム製である点で、一線を画しています。### Puppeteer インストール
Puppeteer にはデフォルトで Chrome が同梱されるので、インストールはこれだけです:
```bash
npm install --save-dev puppeteer
```### smoke.test.js 作成
アプリケーションが煙をあげていないかチェックする、最低限のテストを追加します。
とは言っても、スクリーンショットを 1 枚撮るだけです:```diff
myapp/
├── index.html
├── node_modules
├── package.json
├── package-lock.json
+ └── smoke.test.js
``````js
const puppeteer = require('puppeteer');(async() => {
const browser = await puppeteer.launch();
const page = await browser.newPage();await page.goto('http://localhost:8080/');
await page.screenshot({ path: 'screenshot.png' });await page.close();
await browser.close();
})();
```package.json に test スクリプトの定義を追加しておきます:
```diff
"scripts": {
"start": "http-server ./",
- "test": "echo \"Error: no test specified\" && exit 1"
+ "test": "node ./smoke.test.js"
},
````npm run start` でアプリケーションを起動し、別のターミナルから `npm run test` を実行することでテストができます…:
```bash
(node:8637) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Failed to launch chrome!
/home/ec2-user/environment/myapp/node_modules/puppeteer/.local-chromium/linux-536395/chrome-linux/chrome: error while loading shared libraries: libXcursor.so.1: cannot open shared object file: No such file or directoryTROUBLESHOOTING: https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md
(node:8637) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
```おや、エラーになってしまいました。
解決しましょう。## Troubleshooting Puppeteer on Cloud9
### Run Headless Chrome on EC2 Amazon Linux
エラーの内容や、[TROUBLESHOOTING](https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md) のリンク先を見ると、どうやら依存パッケージが不足しているようです。
この問題は、`shared libraries: libXcursor.so.1` というメッセージやリンク先の手順を手がかりにパッケージをインストールしても、素直には解決しませんでした。しばらく検索したあと、次ような投稿を見つけ、解決することができました。
最高、ありがとう!:- [MockingBot - Run Puppeteer/Chrome Headless on EC2 Amazon Linux](https://mockingbot.com/posts/run-puppeteer-chrome-headless-on-ec2-amazon-linux)
ここに書かれている、必要なコマンドは、次のスクリプトにまとめたので、これを実行するだけで OK です:
[install-chrome-dependencies.sh](install-chrome-dependencies.sh)```bash
sh install-chrome-dependencies.sh
````npm run start` の後に `npm run test` で、今度こそテストが実行され、スクリーンショットが生成されます:
```diff
myapp/
├── index.html
├── node_modules
├── package.json
├── package-lock.json
+ ├── screenshot.png
└── smoke.test.js
```
🎉🎉
### Install a Japanese font
Headless Chrome によってスクリーンショットを撮ることはできましたが、日本語が tofu になっています。
これは Chrome の問題ではなく、Cloud9 のインスタンスに日本語フォントがインストールされていないためです。以下の方法で [VLゴシック](http://vlgothic.dicey.org/) をインストールして解決します:
```bash
sudo yum install -y vlgothic-fonts
```
🎉🎉🎉
## アプリケーション拡張
ここまでで、Cloud9 上で Headless Chrome を使えるようになり、開発のベースは整いました。
あとは自分のアプリケーション開発に生かしてもらえれば良いですが、参考までにアプリケーションを拡張してみます。### 検索機能の追加
index.html を次のように修正します:
```diff
-
+
+
+ Search
+
+
- const date = new Date().toLocaleString('ja-JP-u-ca-japanese', {
- year: 'numeric',
- month: 'short',
- day: 'numeric',
- weekday: 'short',
- });
+ const input = document.querySelector('#name');
+ const button = document.querySelector('#search');
+ const result = document.querySelector('#result');
+
+ button.addEventListener('click', async event => {
+ const name = input.value;
+ const response = await fetch(`/users?name_like=${name}`, {
+ credentials: 'same-origin'
+ });- document.querySelector('main').textContent = date;
+ result.textContent = await response.text();
+ });
```次の図のように、ボタンを押すとユーザーを検索する機能を追加しました:

しかし実際には、HTML を修正しただけでは検索の API `/users` が存在しないため、404 エラーにしかなりません。
[JSON Server](https://github.com/typicode/json-server) をインストールし、API として機能させます:```bash
npm install --save-dev json-server
```中身のデータは `stub.json` として用意し:
```diff
myapp/
├── index.html
├── node_modules
├── package.json
├── package-lock.json
├── screenshot.png
├── smoke.test.js
+ └── stub.json
```stub.json
```json
{
"users": [{
"id": 1,
"name": "John Doe"
}, {
"id": 2,
"name": "Jane Doe"
}]
}
````package.json` には、http-server からのプロキシー設定と `stub` スクリプトを追加しておきます:
```diff
"scripts": {
- "start": "http-server ./",
+ "start": "http-server ./ --proxy http://localhost:3000",
+ "stub": "json-server --watch ./stub.json",
"test": "node ./smoke.test.js"
},
````npm run start` と `npm run stub` は別のターミナルから実行する必要がありますが、起動させれば検索機能がちゃんと動いているのが見られます。
### JSON API のモックテスト
アプリケーションの拡張に合わせて、`smoke.test.js` も拡張してみます:
```diff
+const { URL } = require('url');
const puppeteer = require('puppeteer');(async() => {
const browser = await puppeteer.launch();
const page = await browser.newPage();+ await page.setRequestInterception(true);
+ page.on('request', request => {
+ const { pathname } = new URL(request.url());
+ if (pathname === '/users') {
+ const mockedData = [{
+ id: 3,
+ name: 'Jackson Doe'
+ }];
+ request.respond({
+ contentType: 'application/json',
+ body: JSON.stringify(mockedData)
+ });
+ }
+ else {
+ request.continue();
+ }
+ });
+
await page.goto('http://localhost:8080/');
+
+ await page.click('#name');
+ await page.keyboard.type('doe');
+ await page.click('#search');
+
await page.screenshot({ path: 'screenshot.png' });await page.close();
````/users` へのリクエストをインターセプトして、`stub.json` には存在しないデータを返すようにしています。
`npm run test` の結果はこの通りです:
🎉🎉🎉🎉
# Optional trainings
No content yet
## Install Jest
## Install Webpack
## Install SPA frameworks
# 参考文献
- [MockingBot - Run Puppeteer/Chrome Headless on EC2 Amazon Linux](https://mockingbot.com/posts/run-puppeteer-chrome-headless-on-ec2-amazon-linux)
- [CentOSでもWindowsでも使える! 日本語フォント(ゴシック編) | 株式会社ビヨンド](http://beyondjapan.com/blog/2017/01/japanese-gothic-fonts-on-linux)