TypeScript+webpackでProcessing(p5.js)の環境を構築する

## はじめに

<img width="329" alt="スクリーンショット 2019-04-23 8.39.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2278/8eb08c3e-a043-0e69-90fc-ce6490d29d71.png">


p5.jsは、JavaScriptで実装されたProcessingです。プログラムを書くのも当然ながらJavaScriptになります。Webブラウザで実行できるのが利点です。

ちょっとしたジェネレーティブアートのプログラムを書く場合はJavaScriptのままでも良いのですが、ゲームを作る場合で大規模なプログラムになってくると、型が欲しくなります。

本記事では、TypeScriptでProcessingプログラミングをする環境の構築手順を紹介します。


## とりあえず環境を手に入れたい場合

TypeScriptでp5.jsを書く環境をとりあえず手に入れたい場合は、以下の手順になります。

```bash
$ git clone git@github.com:memememomo/ts-p5js-template.git
$ cd ts-p5js-template
$ yarn
$ yarn watch
```

ブラウザが自動で立ち上がり、以下のような絵が表示されると思います(されない場合はリロードしてください)。

<img width="377" alt="スクリーンショット 2019-04-21 17.43.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2278/5f16d9f0-6b2f-a95a-0e67-1c19424c67d3.png">

あとは `src/main.ts` を編集するだけです。

以降は、スクラッチで環境を準備する手順と各種設定の解説となります。


## yarnのインストール

パッケージ管理としてyarnを利用します。Homebrewを利用してインストールします。

```bash:yarnのインストール
$ brew install yarn 
```

## プロジェクトディレクトリの作成

プロジェクトディレクトリを作成します。

```bash
$ mkdir ts-p5js-template
$ cd ts-p5js-template
```

## package.jsonの生成と必要モジュールのインストール

yarnコマンドを使用して、各種必要ファイルを生成します。

```bash
$ yarn init -y # package.json
```

yarnコマンドを使用して、必要なモジュールをインストールします。

```bash
$ yarn add webpack --dev      # webpackの本体
$ yarn add webpack-cli --dev  # webpackコマンド
$ yarn add typescript --dev   # TypeScript
$ yarn add ts-loader --dev    # webpack用のTypeScriptローダー
$ yarn add @types/p5 --dev    # p5.jsの型ファイル
$ yarn add concurrently --dev # 複数のコマンドを同時実行
$ yarn add browser-sync --dev # ファイル変更監視とブラウザリロード
```

## TypeScriptの設定ファイル(tsconfig.json)を作成

TypeScript再入門 ― 「がんばらないTypeScript」で、JavaScriptを“柔らかい”静的型付き言語に
https://employment.en-japan.com/engineerhub/entry/2019/04/16/103000

上記のページを参考に設定します。

```js:tsconfig.json
{
  "compilerOptions": {
    "sourceMap": true,
    // TSはECMAScript5に変換
    "target": "es5",
    // TSのモジュールはES Modulesとして出力
    "module": "es2015",
    // node_modulesからライブラリを読み込む
    "moduleResolution": "node",
    // 暗黙的なanyを許可する(頑張らない)
    "noImplicitAny": false,
    // コメントは削除しない
    "removeComments": false,
    // コンパイルターゲットがES5時にfor-of文を使えるようにする
    "downlevelIteration": true
  }
}
```

## p5.js用の型ファイルを作成(global.d.ts)

p5.js用の型ファイルを作成します。

```ts:global.d.ts
import module = require('p5');
import * as p5Global from 'p5/global'

export = module;
export as namespace p5;
declare global {
    interface Window {
        p5: typeof module,
    }
}
```

## webpack用の設定ファイルを作成(webpack.config.js)

webpack用の設定ファイルを作成します。

```js:webpack.config.js
const path = require('path');

module.exports = {
  // production の場合、最適化された状態で出力される
  // development の場合、ソースマップが有効でJSファイルが出力される
  mode: 'development',

  // エントリーポイント
  entry: './src/main.ts',

  module: {
    rules: [
      {
        // 拡張子 .ts の場合
        test: /\.ts$/,
        // TypeScript をコンパイルする
        use: "ts-loader"
      }
    ]
  },
  // import 文で .ts ファイルを解決する
  resolve: {
    modules: [
      "node_modules"
    ],
    extensions: [".ts", ".js"]
  }
};
```

## package.jsonにタスクを設定

package.jsonに `scripts` を追記して、タスクを設定します。webpackによるビルドコマンドを設定しています。

```js:package.json
{
   ...
   "scripts": {
       "build": "webpack",
       "watch": "concurrently \"browser-sync start --server -w\" \" webpack --watch\""
   },
   ...
}
```

これで `yarn build` などでタスクが実行できます。

## HTMLファイルとTSファイルを作成



```ts:src/main.ts
import * as p5 from 'p5';

const sketch = (p: p5) => {
    p.preload = () => {
    };

    p.setup = () => {
        p.resizeCanvas(p.windowWidth, p.windowHeight);
    };

    p.windowResized = () => {
        p.resizeCanvas(p.windowWidth, p.windowHeight);
    };

    p.draw = () => {
        p.background(100);
        p.ellipse(100, 150, 180, 60);
    }
};

const sketchP = new p5(sketch);
```

```html:index.html
<html>
<head>
    <script src="dist/main.js"></script>

    <link rel="shortcut icon" href="https://p5js.org/assets/img/favicon.ico">
    <link rel="icon" href="https://p5js.org/assets/img/favicon.ico">

    <style>
        * {
            padding: 0px;
            margin: 0px;
        }
    </style>
    <script>
    </script>
</head>
<body>
</body>
</html>
```

## 実行

以下のコマンドを実行すると、ブラウザが立ち上がります。

```bash
$ yarn watch
```

以下のような絵が表示されると思います。(表示されない場合はリロードしてみてください。)

<img width="377" alt="スクリーンショット 2019-04-21 17.43.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2278/5f16d9f0-6b2f-a95a-0e67-1c19424c67d3.png">

`src/main.ts` を編集すると、自動で変更が検知されて、ブラウザがリロードされます。

以上で、TypeScriptでProcessingを書く環境ができあがりました。


## まとめ

TypeScript+webpackで、Proessingを書く環境を構築しました。これである程度の規模のゲーム製作でも快適に行えるのではないかと思います。


## 参考リンク

最新版TypeScript 3.0+webpack 4の環境構築まとめ（React, Vue.js, Three.jsのサンプル付き）
https://ics.media/entry/16329/#webpack-ts

webpack 4 入門
https://qiita.com/soarflat/items/28bf799f7e0335b68186

p5-typescript-starter
https://github.com/Gaweph/p5-typescript-starter