Adobe Express add-onの開発やってみた02

Express

前回に引き続きExpressの拡張機能の開発です。今回は実際のコードに触れるわけですが前回一番シンプルなコードのテンプレートをnpxで引っ張ってきました。しかしこのテンプレート以外にもいくつかパターンのテンプレートが用意されています。
因みに前回のコマンドは以下のようなコマンドでした。

hello-worldはアプリケーションの名前で自分で好きな名前をつけられます。そして–template javascriptはjavascriptのテンプレートを使うというオプションだったのです。公式のドキュメントからコマンドのオプションが一覧で見れます。ReactやTypeScriptを使ったサンプルがあるのもわかります。いちいちオプションを打つのが面倒な場合はnpx @adobe/create-ccweb-add-on –appname だけ打てば対話形式でテンプレートを選ぶことも可能です。

dialog_cli
対話形式でも選べる。

途中でSandBoxを含めるかどうか聞かれます。このSandBoxはExpressのアプリケーションを動かすAPIのスコープなのですがこれを完全に分離した状態のテンプレートを用意してくれます。SanBoxの詳細は後述する項目を参照。今回はJavaScriptのテンプレートでSandBoxを使用を選択した状態で進めます。

テンプレートフォルダー
JavaScriptのテンプレートのフォルダー構成。

ファイル構成

必須のファイルは大まかに以下のような構成になっています。

  • manifest.json
  • index.html
  • package.json
  • index.js(ts)

manifestはUXPやCEP同様アプリケーションの重要な項目を宣言するファイルになります。index.htmlはファイルのUIの土台になるhtml。index.jsはJavaScript。package.jsonは必要なnpm modulesが記載、またアプリケーションを立ち上げるのに使用するコマンドも記載されています。これは前回の記事を見てもわかる通りwebpackを使う、使わないに関わらずコンパイルの作業は必須になります。

Express専用のモジュール

ReactやTypeScriptのテンプレートを選ぶとお馴染みのモジュールもpackage.jsonに記載されていますが何やら見慣れない項目もあります。

  • @adobe/ccweb-add-on-scripts
  • @adobe/ccweb-add-on-sdk-types

ですね。これらが仮想環境でサーバーを立ててExpressに接続してアプリケーションを走らせているのだと思いますが現状中身はよくわかっていません。またテンプレートデータですとsrcフォルダー内のコードをdistフォルダーに書き出してdistフォルダー内の内容をそのままExpress上で走らせています。package.jsonのscriptsの内容を見るとわかります。以下は一番シンプルなwebpackを使わないテンプレートのコード。

buildでコードをコンパイルしてstartで走らせるのはわかります。

テンプレートの中身

いよいよコードの中身に触れていきます。皆さんご存知の通りAdobeの拡張機能の開発はHTML,CSS,JavaScriptベースのブラウザと同じ、もしくは似たような機能を持ったUIを構築する部分とAdobeのアプリケーションにアクセスするJavaScriptのAPIに分かれています。このExpressも例に漏れずセキュリティの関係か似たような関係になっています。
とはいえ実際にユーザーがボタンを押すなどの何かしらのアクションの発火を管理する仕組みはブラウザ上のUIで管理することになります。この両者をつなげる役割のAPIをCommunication APIsと呼んでいたりします。またExpressのドキュメントにアクセスして実際にイメージを操作するAPIをDocument APIsと呼んでいたりします。この辺りの仕組みは図解はDocument APIsのチュートリアルで触れられています。ある程度目を通しておいた方が良いでしょう。
そして今回二つのフォルダーにコードが分かれています。

  • SandBox
  • ui

そして各ファルダーに以下ののようなファイルがあるでしょう。SandBox内にドキュメントにアクセスするコードが、uiのフォルダーがhtml上で動くコードになっています。そして以下のように同じようなファイル構成になっているでしょう。

  • add-on…d.ts
  • jsファイル
  • tsconfig.json

ここでお気づきになると思いますが今回TypeScriptのテンプレートを選んだわけでも無いのにTypeScriptの設定ファイルが含まれています。SandBox内のcode.jsでもuiフォルダー内のindex.jsでも何かしらExpressのモジュールをimportしています。これはadd-on-sandbox-sdk.d.ts内のimport分とつながっています。

add-on-sandbox-sdk.d.tsがExpressの各モジュールとindex.jsの間でモジュール名を再定義しています。なぜこんなことをやっているのか理由はよくわかりませんがとにかくこれでimport文が多少は簡略化されているみたいです。因みにDO NOT modify this file.と言うコメント通りこの型定義ファイルの中身は触らない方が良さそうです。そして各種tsconfig.jsonファイルですが基本の設定はアプリケーションフォルダー直下のtsconfig.jsonファイルが大元の設定ファイルになっていてuiフォルダーとSandBoxフォルダー内のtsconfig.jsonファイルはそこから拡張して各APIに内容を合わせているようです。

code.js

ここからcode.js、Document APIsに触れます。SandBoxApiにcreateRectangleと言うメソッドがありますがこれはExpressのドキュメントにそのメソッド名の通り長方形のオブジェクトを作成します。express-document-sdkからimportされているeditorと言うclassがExtendScriptなんかのappと似てような役割になっているでしょう。細かいAPIの内容に触れません。重要なのはruntime.exposeApiメソッドでuiのスコープの範囲でもコードでも実行できるようにします。uiのスコープにexpose(解放)するということでしょう。因みにmanifest.jsonで”documentSandbox”: “sandbox/code.js”と言う項目があります。つまりこのDocument APIsのコードはどこから引っ張るかmanifest上での宣言が必要と言うことです。

index.js

このindex.jsで上でブラウザ上の操作を管理しますが同様にDocument APIsから解放されたメソッドもimportしてここでボタンを押した時などに実行させるようにします。この時にaddOnSandboxSdkというモジュールが重要になります。addOnUISdkを走らせる必要があるのですが案の定これは異なるファイル環境から読み込むためかPromiseによる非同期での読み込みになっています。なのでテンプレートのコードではこのモジュールの読み込みが終わるまでコードが走らないように工夫しています。

ボタンの状態が読み込みが終わるまでdisalbedになっています。SandBox内で解放したcreateRectangleメソッドはsandboxProxyオブジェクトから非同期で実行できます。

外側からは非同期なのにDocument APIsのSandBox内実行は同期?

CEPもそうなんですが外側からの実行非同期なのは全く異なる環境下のJSファイルを実行するので非同期なのですがアプリケーションのAPIの実行自体は同期です。だったらUXPのアプリケーション側の実行もUIと切り離して(既にPhotoshopは切り離されてるが)外側からの実行は非同期で中のコードは同期で良かったんじゃ無いとか思ってしまいます。実際UXPの非同期操作だって並列実行できるわけじゃないし。

Express add-on完全なモダン環境?

CSSのtransitionとかGrid-Layoutが使えました。ブラウザ上で動くアプリケーションという性質上UXPと違いおそらく完全にモダンな環境で動くとは思います。もちろんSandBox側からはブラウザにアクセスするようなAPIは使えません。SandBoxとブラウザを繋ぐシステムはどうやらcomlinkというシステムがベースになっているみたいです。またTypeScriptもほとんど完全な形で使えそうです。

豊富なチュートリアルとサンプル

これから開発する開発者に向けて豊富なサンプルコードとチュートリアルが用意されています。まずはGrid System add-onのサンプルのチュートリアルから始めと良いでしょう。その他画像をブラウザのuiからExpressのドキュメントにドラッグアンドドロップするサンプルや外部webサービスのAPIと連携するサンプルも沢山あります。以下よりアクセスしてみてください。

参考

Beer 寄付してサイトを応援する。