😊

ExtendScriptをWebpack+Typescriptで組めた

2023/03/06に公開

動機

最近学び始めた AE のスクリプト&Javascript
C 系を組んでいた自分にとっては型宣言も無ければ、JS の構文を調べても ExtendScript だと最近の構文が使えなかったりする・・・。
ということで調べてみました。

GitHub のリンク貼っておきます。
GitHub : https://github.com/jajasun/ae-script-ts-test

まずは ExtendScript を ES5,6 で書きたい

「Adobe ExtendScript を JavaScript ES6 で記述する」
参考リンク:https://qiita.com/yukkuriesu/items/95ec37307348b71ec28f

webpack ってのを使えば ES6 とか使えるのか!

npm install webpack webpack-cli webpack-dev-server webpack-es3-plugin

でも JS は型が無くてわかりづらい・・・

型が無いとプロトタイプとかは組みやすい、ある程度知識のある人にとってはコンパイルエラーが出にくいから作業しやすいのはわかります。
ただ初心者からすると動作時しかわからんエラーの対処に時間がかかる・・・

例)

var items = app.project.items;
for (var i = 1; i < app.project.numItems; i++) {
  var item = app.project.items[i];
  // ... itemって何が入ってるの?
  // 候補から選択しても型がどうなってるかわからないので、適切な変数がどれかわからない
}

Typescript は型もあって、JS に出力するものなのか!

認識は間違っていると思います。
ただ、今はとりあえずこの認識で進めました。

npx tsc --watch

TS を JS に動的に変換してくれるコマンド

えっ?これ組み合わせたらできるのでは?

javascript(ES6) → webpack → ExtendScript
が可能なら
Typescript → javascript → webpack → ExtendScript
もできるのでは・・・と思い、調べてみたところ、

下記サイトを見つかました。
Gulp + webpack + TypeScript で開発環境を作成する

その中で webpack を使用して変換してそうな部分の
webpack.config.js を参考にさせていただきました。

結果

package.json

{
  "name": "ae-script-ts-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "extendscript-es5-shim-ts": "^0.0.1",
    "ts-loader": "^9.4.2",
    "types-for-adobe": "^7.0.12",
    "typescript": "^4.9.5",
    "webpack": "^5.75.0",
    "webpack-cli": "^5.0.1",
    "webpack-dev-server": "^4.11.1",
    "webpack-es3-plugin": "^1.5.2"
  }
}

webpack.config.json

var ES3Plugin = require("webpack-es3-plugin");
module.exports = {
    entry: "./src/main.ts",
    module: {
        rules: [
            {
                test: /\.ts$/,
                use: "ts-loader"
            },
        ]
    },
    resolve: {
        extensions: [".ts", ".js"]
    },
    output: {
        filename: "./src/out/main.js",
        path: __dirname
    },
    mode: "development",
    devtool: false,
    plugins: [new ES3Plugin()]
};

./src/main.ts

// ウィンドウに文字列とボタンを追加して描画
var thisWnd = this as any;

if (thisWnd instanceof Panel) {
} else {
  thisWnd = new Window("palette", "test-ts-tool", [100, 100, 600, 400] as Bounds);
  let wnd: Window = thisWnd; // 予測出るように
  wnd.show();

  wnd.add("statictext", [15, 15, 600, 30] as Bounds, "static-text-test");
  wnd.add("button", [15, 30, 100, 45] as Bounds, "test-button");
}

コマンド

npx webpack

出力結果が以下

コメントアウトされていますが、実際には動作するよう出力されています。
./src/out/main.js

/******/ (function () {
  /******/ "use strict";
  /******/ var __webpack_modules__ = {
    /***/ "./src/main.ts":
      /*!*********************!*\
          !*** ./src/main.ts ***!
          \*********************/
      /***/ function () {
        var thisWnd = this;
        if (thisWnd instanceof Panel) {
        } else {
          thisWnd = new Window("palette", "test-ts-tool", [100, 100, 600, 400]);
          var wnd = thisWnd; // 予測出るように
          wnd.show();
          wnd.add("statictext", [15, 15, 600, 30], "staic-text-test");
          wnd.add("button", [15, 30, 100, 45], "test-button");
        }
        /***/
      },
    /******/
  };
  /************************************************************************/
  /******/
  /******/ // startup
  /******/ // Load entry module and return exports
  /******/ // This entry module is referenced by other modules so it can't be inlined
  /******/ var __webpack_exports__ = {};
  /******/ __webpack_modules__["./src/main.ts"]();
  /******/
  /******/
})();

紆余曲折・・・(まとめ)

JS も Typescript も ExtendScript も Node も初心者すぎてよくわからないことがたくさんあります。
だから「Typescript + ExtendScript」で調べてみて出てきたものを試してみたものの、よくわからないパッケージをたくさん利用していてよくわからないエラーに悩まされることが非常に多くありました。

ExtendScript→ES6→Typescript と 1 つずつ進めて、できる限り最小限に実現できたと思います。

追記

  • namespace , private/public 使用可能
  • AE のオブジェクトの new はコンストラクタが無いため使用できない
const comp = new CompItem();

app.project.items 等、代入して対応する

Discussion