Adobe ExtendScript をJavaScript ES6で記述する

# 追記(2025/3/18)
ES3記法のExtendScriptから、ES6をサポートするUXPへと移行が進んでいるみたいです！
https://developer.adobe.com/indesign/uxp/resources/migration-guides/extendscript/
新規でAdobe拡張を学ぶならUXPを触った方が手っ取り早いのでこの記事の有用性はほとんどないですが、まだ前者でしかできないことがそこそこあるっぽいので記事自体は残しておきます。


# 目的
Adobe ExtendScriptはES3という非常に古い文法しか使えません。
1999年12月に出たJavaScriptのバージョンです。

 有料ソフトなのに保守ガバガバすぎませんか？ 
何か理由があるのでしょうか。
とにかくclassが使いたかったので、ES6を導入します。

[typescriptでExtendScriptを書いてみた](https://qiita.com/tetsuoh/items/dcdf75b87613bc85e8ab)
としていることは近いですが、webpackに慣れてる方にとっては取っ掛かりがいいのかなと思い執筆に至りました。

## 筆者の環境
- Windows 10 Home  
- After Effects 2021(18.0)  
- WSL  
(これにより使用するコマンドがUbuntu / Mac準拠になります。
後で出てくる sudo apt install はWindowsでは出来ないので、
「npm インストール」とかで逐次ググってみてください。)

## 手段の概要
ES6で書かれたプログラムを webpack-es3-plugin でES3にトランスパイルします。
非常に簡単なため、記事の大半はwebpackのチュートリアルです。

## 手順

### 元となるスクリプトファイルを記述する
今回は以下のファイルを用います。
新しいフォルダを作って、そこにこいつだけがいる状況が望ましいです。
(後で色々ファイルが増えてきて管理が大変になるからです)

```js:hello.jsx
class Person {
  constructor(name) {
    this.name = name;
  }
  intro() {
    alert("私の名前は" + this.name + "です。");
  }
}

hito = new Person("ほげ");
hito.intro();
```

念のためこれを実行してみると、

```
Syntax Error:
予約語 'class' が正しく使用されていません <= line:1 column:1 file: [パス]
```

となってしまいます。

### 必要なパッケージをインストールする

webpackという、複数ファイルを一つのjsファイルにまとめるぞ～って感じのご機嫌なパッケージを用います。
nodejs, npmはJavaScript関連のライブラリをまとめて管理できるヤツです。
詳しくは知りませんが使えてるのでOKです。

以下のコマンドはhello.jsxがあるディレクトリと同じ階層で行ってください。

```
$ sudo apt install nodejs npm
$ npm install webpack webpack-cli webpack-dev-server webpack-es3-plugin
```

### webpack用のconfigを記述する
以下のファイルを作成します。

```webpack.config.js
var ES3Plugin = require("webpack-es3-plugin");
module.exports = {
    entry: './hello.jsx',
    output: {
        filename: 'output.js',
        path: __dirname
    },
    mode: 'development',
    devtool: false,
    plugins: [new ES3Plugin()]
};
```

この中身ですが、

```webpack.config.js
    entry: './hello.jsx',
```

が入力ファイルを指すことと

```webpack.config.js
    output: {
        filename: 'output.js',
```

が出力先のファイルを指すことを理解してもらえれば大丈夫です。
(webpack-es3-pluginの都合で出力ファイルの拡張子は.jsにする必要があります。
出力された後.jsxに手動で変える分には構わないです。)

### ファイルを出力、動作確認
以下のコマンドを実行します。

```
$ webpack
[webpack-es3-plugin]: start to convert js files into es3 compatible...
[webpack-es3-plugin]: done
asset out/output.jsx 335 bytes [compared for emit] (name: main)
./hello.jsx 180 bytes [built] [code generated]
webpack 5.61.0 compiled successfully in 107 ms
```

最後にsuccessfullyと出ていたら成功しています。

output.jsを見てみましょう。

```output.js
/******/ (function () {
    var __webpack_exports__ = {};
    /*!******************!*\
      !*** ./test.jsx ***!
      \******************/
    var Person = /** @class */ (function () {
        function Person(name) {
            this.name = name;
        }
        Person.prototype.intro = function () {
            alert("私の名前は" + this.name + "です。");
        };
        return Person;
    }());
    hito = new Person("ほげ");
    hito.intro();
    /******/ 
})();
```

見事にclassを用いた記述が消え、ES3で通るようになっています。
あとはこれを実行して、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419151/235f1a13-618a-06b1-54b5-b26e9be318d7.png)

無事動きました！これで手順終了です。

## 記事の不備かな？と思ったら
筆者がこの手順に行きつくまでに引っかかった箇所とその対処を紹介します。
サンプル数が1なので、基本的には私を参考にするより自己解決を推奨します。

### webpack-cliが無いと言われる

```
$npm install webpack-cli -g
```

とします。-gはグローバルインストールをするためのオプションです。
ACCESS ERRORだなんだ言われたらsudoを付けましょう。

また、wslの場合グローバルインストールしたパッケージを読んでくれなかったので、
以下の記事の方法で対処しました。
[npm install -gでグローバルインストールしたのに見つけてくれない](https://qiita.com/chkk525@github/items/ea1c2a110bf74efd843c)
### webpack-dev-serverが実行できない
nodeのバージョンによるものだと思われます。
[OS名] node アップデート 等で検索してみてください。
私は以下が参考になりました。
[Ubuntuに最新のNode.jsを難なくインストールする](https://qiita.com/seibe/items/36cef7df85fe2cefa3ea) 

## おわりに
webpack-es3-pluginの挙動がちょっと分からなくて、
inputするファイルの拡張子を.jsにするとinput元のファイルまで変換されてしまったり、
webpack-dev-serverするとpluginに挙動が上書きされているのかそもそも変換すらしてくれなかったりと、
webpackの機能をフルで利用することは出来ませんでした(恐らく方法はあると思います)。
誰かの参考になれば幸いです。