BizRobo!ハック：babel/standalone と Polyfill を使ってDSをパワーアップする方法

## はじめに

WebサイトをBizRobo!で自動化する方法は現在3つあり、それぞれの特徴と使い所について経験者視点から以下にまとめました。

https://qiita.com/macrisis/items/e3d45077dcd1ffffdfb8#%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%81%AE%E7%89%B9%E5%BE%B4%E3%81%A8%E6%B4%BB%E3%81%8B%E3%81%97%E6%96%B9

記事の中でも書いたとおり今後の有望株はDA組込みブラウザであるChromiumだと思っていますが、今もなお圧倒的な使いやすさを誇るデフォルトブラウザは人気が高く、もう少しChromiumが成熟するまではデフォルトブラウザ使いたいなぁというのも分かります。

今回はなんとかデフォルトブラウザの寿命を伸ばす方法がないかと実験してみた結果の共有です。

結論としては、
> babelで動的にコンパイル[^1]しPolyfillで機能を補完したらわりといけた。

感じです。

具体的な使い方、手順を動画にまとめてみました。
<iframe width="560" height="315" src="https://www.youtube.com/embed/vmgmzer-wDA?controls=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

以降、手順の整理をしていきます。

#### 前提と注意
* 検証は BizRobo! 10.7.0.4 で実施しました。
* 動画中のロボットやHTMLのページは [GitHub](https://github.com/1010-junji/bizrobo-tips/tree/main/usingBabel/Library) からダウンロードできます。
* 実際にbabelを試すときには `<script type="text/babel">` への変換漏れがないように各自で調整してください。

## Babelって何？

まずはBabelについて。今回DSをパワーアップ（そのままでは処理できないサイトを処理できるようにする）させるために使用する "技" がBabelなのですが、Web開発に詳しい一部の人を除き「それって何？」という感じだと思います。

名前からするに[バベルの塔](https://www.wordoflife.jp/%E3%80%8A3%E5%88%86%E3%81%A7%E3%82%8F%E3%81%8B%E3%82%8B%E3%80%8B%E3%83%90%E3%83%99%E3%83%AB%E3%81%AE%E5%A1%94%E3%81%A8%E3%81%AF%E4%BD%95%E3%81%8B%EF%BC%9F/)を連想します。同じJavaScript同士なのに意思疎通が取れないなんて。。。という悲哀が感じられますね。

公式サイトによると

https://babeljs.io/docs/en/

> #### Babel is a JavaScript compiler
> Babel is a toolchain that is mainly used to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in current and older browsers or environments. Here are the main things Babel can do for you:
> 
> * Transform syntax
> * Polyfill features that are missing in your target environment (through a third-party polyfill such as core-js)
> * Source code transformations (codemods)
> * And more! (check out these videos for inspiration)

と冒頭に記載されており、つまりは「Babelは古いブラウザ環境でECMAScript2015[^2]以降のコードを下位互換性のあるバージョンのJavaScriptに変換するコンパイラ」ということです。
難しい専門用語を素人でもわかるように噛み砕いて言い直してくれる。的な感じでしょうか。。

つまり古いブラウザ環境であるBizRobo!のデフォルトエンジンは、Babelを使うことによりECMAScript2015以降のコードが含まれたWebサイトでも操作できるようになる。という代物です。

オープンソースで開発されておりとても便利なので、皆さん[寄付](https://opencollective.com/babel)しましょう！

## どうやって使う？

通常Babelを使うのはソフトウェアの出荷・リリース前で、Babelでコードをコンパイルして本番環境にリリースしたりするのですが、今回は既にリリース後のコードに対してコンパイルをする必要があるので、ページを読み込んだタイミングでBabelを実行するために `@babel/standalone`[^3]というモジュールを使います。

DSの中で利用するためには、

1. 読み込みページのHTML解析が開始される前に 
1. Babelで変換する箇所を指定するとともに、
1. babel/standalone のコードを組み込む 　

必要があります

### 読み込みページの内容を書き換える。

BizRobo!は自分自身の中にブラウザエンジンを持っているので、読み込んだページを解析してWebページを描画するまでの間に特定の処理を組み込む事ができます。[^4]

以下の通り、`ロボットの設定`メニューから`デフォルトオプション`を開き、`ページロード中`タブ内の`ページの変更`オプションを設定します。
![desktop-monitoring2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1524794/cf054361-07db-9e23-8755-97986634f0f6.gif)
`ページの変更`では「すべてのページで同じ」か「URLに依存」のどちらかをターゲットにすることができますが、実際に運用するロボットに設定をする場合には「URLに依存」を選択して影響範囲を絞ることをおすすめします。

### Babelで変換する箇所を指定する
![set-pattern.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1524794/76fc12f3-08c7-718f-bb86-f56bf184750d.png)
Babelで変換したいコードを含む `<script>` タグを特定して `<script type="text/babel">` に書き換えます。これにより後で組み込む babel/standalone のコードが指定タグ内のJavaScriptコードをコンパイルします。

```html:パターン
<script(.*?)>
```
```javascript:エクスプレッションを置き換え
contains($1, "text/javascript") ? 
    replaceText($0,$1,replaceText($1,"text/javascript","text/babel")) : 
    ( length($1) > 1 ?
        replaceText($0,$1,$1 + >> type="text/babel"<<) :
        replaceText($0,">",>> type="text/babel"><<) )
```
上のコードはscriptタグに `type="text/javascript` が設定されている場合と `type` 自体が設定されていない場合にのみ `type="text/babel` を設定するための設定です。

場合によってはscriptタグにそれ以外の `type` が設定されているかもしれませんが、そういったサイトを扱う際には上のコードを修正する必要があるかもしれません。


### babel/standalone コードの組込み
![set-text.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1524794/4551ba1c-1c01-1586-bba5-1cd84d655072.png)
上のステップでコンパイルする箇所のマーキングが終わっているので、あとはBabelを読み込むためのタグを以下のように組み込む必要があります。

```html:このテキストを検索
</title>
```
```html:このテキストに置き換え
</title>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
```
このサンプルでは公式サイトの案内に沿って[UNPKG](https://unpkg.com/)で提供されているインターネット上のコードを使っていますが、その他のCDNで提供されているモジュール[^5]を使ってもいいと思います。

もしくは「実行するたびにインターネットに接続したくない」という場合には NPM からモジュールをダンロードし、ローカルファイルとして読み込ませるのもありかもしれません。

```sh:npmで取得
npm install --save @babel/standalone
```
何にせよ、デフォルトブラウザでBabelを使う手順としては以上です。


## Polyfillって何？

https://remysharp.com/2010/10/08/what-is-a-polyfill

[MDN Web Docs](https://developer.mozilla.org/ja/docs/Glossary/Polyfill) によると「この単語の創案者である Remy Sharp による記事（上記）」では以下のように定義しています。

> A shim that mimics a future API providing fallback functionality to older browsers.

つまりはECMAScript2015以降の機能をサポートしていない古いブラウザーで、その機能を使えるようにするための拡張機能のようなものです。実はBabelにも `@babel/polyfill` としてポリフィルの機能が用意されていたりします。

ただBizRobo! 10.4 以降はデフォルトブラウザにも同様にポリフィルの機能が搭載されているので、そちらを使っていきます。（メーカーのサポートも受けられるので）

## どうやって使う？

![set-polyfill.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1524794/315d0a30-2bd2-8254-2360-326dbcb48e2f.png)
Babel同様 `ロボットの設定` メニューから `デフォルトオプション` を開き、`JavaScript実行`タブを選択します。

画面下部の `JavaScriptポリフィル` に対して「＋」ボタンで追加する機能が選べますが、何を追加すべきかの判断は ECMAScript2015 自体の知識がないと戸惑いますね。。。

ちなみに、こちらのサイトは参考になりました。

https://www.webdesignleaves.com/pr/jquery/javaascript_02.html

また、`Browser Tracer` 機能でエラーを分析することでどの機能が不足しているか解析することができるよう[^6]なのですが、面倒な場合は「すべて」を選んでしまうのもありかもしれません。（よく理解しないまま実装してしまうのは問題が発生したときに詰むので、お勧めはしません。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1524794/9051bf3e-fda7-a6c3-8dc5-0d3914fb9b08.png)
上の図は組み込まれている Polyfill のオブジェクト/APIを示していますが、一番上に `カスタム` というアイテムがあって、これを選ぶと以下のような画面が出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1524794/4aacba3a-9f4b-68f1-9184-9303147044cb.png)
これはユーザーが自身でオブジェクト/APIをコードを貼り付けて実装することができるインターフェイスのようです。[^7]　

その際の組み込まれていないポリフィル探索に、先にも引用した MDN Web Docs というサイトは役に立ちます。

https://developer.mozilla.org/ja/docs/Web/API/Fetch_API/Using_Fetch

## まとめ

BabelもPolyfillもあくまで処置であり解決策ではないので、やっぱりDA組込みブラウザを使って実装するというのが安全な気もします。

とはいえ、社内のWebシステムのように頻繁には変更されないシステムなら、ロボットに任せる固定のワークフローの範囲でBabel、Polyfillが問題なく動作することが確認できれば十分実用には耐えられると思います。

一方で、SaaSのロボット化やB2Cサイトの操作などWebフロントがわりと変化しやすく、しかもそのタイミングが読めないものについては、ある日突然のサイト変更でBabel、Polyfillどちらでも対応できない状況に陥った場合、ロボット自体を作り直さなければならないことにもなり得るので、注意が必要ですね。

って、この問題は影響の多少はあれどRPA全般の課題ですね。。
何でもかんでもロボット化はダメです。

## 使用上の注意（追記：06/03）

ちなみに本件のようなページの書き換えは、Webのコンテンツセキュリティーポリシー（CSP）にてWebサービス側から禁止されていることが多いです。
というのも、第三者がスクリプトを注入してWebの挙動を変えてしまうことは、普通に考えればセキュリティ上問題ありますよね。
意図せず外部サイトをクラッキングしてしまわないように、あくまで自社のローカルシステムなど、自分/自社で管理できる範囲で行いましょう。

とはいえ、Salesforceなど一般的なビジネス向けSaaSでは予めセキュリティ対策としてCSP[^8]によりbabelの差し込みはブロックされてしまいますが。

## 参考になるサイト

* https://tech.techtouch.jp/entry/build-and-understand-babel-plugin




[^1]: babelはバイトコードやアセンブルなどのより低レベルなコードを生成しているわけではなく、単にJavaScriptを同じレベルの（古い仕様の）JavaScriptに変換しているだけなので、トランスパイラだと思っていますが、の公式ページには「コンパイル」と書いてあるので、コンパイルという言葉を使っています。
[^2]: ECMAScript2015 と ES6 は同義です。
[^3]: https://babeljs.io/docs/en/babel-standalone
[^4]: 今回のようなケース以外ではほぼ使い道はないですが。。
[^5]: https://www.cdnpkg.com/babel-standalone　など
[^6]: [マニュアル内](https://docshield.kofax.com/RPA/ja_JA/10.7.0_oc6xl3vcnp/help/kap_help/reference/c_optionsref.html) に「エラーの場合、JavaScript コンソールには、存在しない JavaScript オブジェクトが表示されます。この情報に従って、必要なポリフィルが見つかり、適用してエラーを解決できます。」の記述あり。
[^7]: [マニュアル内](https://docshield.kofax.com/RPA/ja_JA/10.7.0_oc6xl3vcnp/help/kap_help/reference/c_optionsref.html) に「特定の JavaScript オブジェクトまたは API をサポートするカスタム コードを含めることもできます。カスタムの実装を含めるには、[追加] (+) をクリックし、リストから [カスタム] を選択します。[カスタム] ダイアログ ボックスには、[名前] と [コード] の 2 つのペインが含まれています。[名前] ペインでコード実装の名前を指定し、[コード] ペインに JavaScript コードを貼り付けます。」の記述あり。
[^8]: https://developer.salesforce.com/docs/component-library/documentation/ja-jp/lwc/lwc.security_csp