Babylon.jsをTypeScriptで書いてwebpackを使ってWebGLを使うときのボイラープレート

# 概要

## 想定読者

- Webで3Dを書くための[Babylon.js](https://www.babylonjs.com/)に興味がある方
- [TypeScript](https://www.typescriptlang.org/)でBabylon.jsを使ってみたい方
- [npm](https://www.npmjs.com/), [webpack](https://webpack.js.org/)などのJavaScriptのエコシステムについて基本的な知識がある方

## 前提

node, npmが使えることが必要です。

使用するnpmモジュールは、下記のとおりです。

```
    "babylonjs": "^4.0.3",
    "babylonjs-gui": "^4.0.3",
    "babylonjs-materials": "^4.0.3",
    "ts-loader": "^6.0.4",
    "webpack": "^4.39.3",
    "webpack-cli": "^3.3.8"
```

## 利用するソース

下記に置きました。エントリ執筆時点のタグは0.0.1です。

[https://github.com/hrkt/babylonjs-typescript-webpack-boilerplate/releases/tag/0.0.1](https://github.com/hrkt/babylonjs-typescript-webpack-boilerplate/releases/tag/0.0.1)


# 動かすには

```console
git clone https://github.com/hrkt/babylonjs-typescript-webpack-boilerplate.git
npm install
npm run watch
```

ブラウザでindex.htmlを開くと、下図のような画面が見えるはずです。

![sphere.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65002/df40d3f7-989a-4e20-a0b3-685a43747118.png)

# 説明

基本的に、「[https://doc.babylonjs.com/features/npm_support](https://doc.babylonjs.com/features/npm_support)」の内容を利用しています。

変更点について、適宜「（差分）」として補足します。

## tsconfig.json

（差分）
- TypeScript用の設定ファイルのtsconfig.jsonでは、compilerOptionsで、"module": "es2015"としています。
- 対象とするファイル、しないファイルについて、それぞれincludeとexcludeの項目で指定しています。


```json
{
    "compileOnSave": true,
    "compilerOptions": {
        "target": "es5",
        "module": "es2015",
        "outDir": "js",
        "sourceMap": true,
        "types": [
            "babylonjs",
            "babylonjs-gui",
            "babylonjs-materials"
        ]
    },
    "include": [
        "src/**/*"
    ],
    "exclude": [
        "node_modules",
        "**/*.spec.js"
    ]
}
```


## webpack.config.js

（差分）
- WebPack用の設定ファイルのwebpack.config.jsでは、node_modules以下のファイルを別のバンドルとしてビルドする設定を入れています。
- 冒頭で、必要なモジュールのrequireを行っています。

```js
const path = require('path')
const webpack = require("webpack")
module.exports = {
    optimization: {
        splitChunks: {
          cacheGroups: {
            commons: {
              test: /[\\/]node_modules[\\/]/,
              name: "vendor",
              chunks: "initial",
            }
          }
        }
      },
    mode: "development",
    entry: {
        app: './src/app.ts'
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js'
    },
    resolve: {
        extensions: ['.ts', '.tsx', '.js']
    },
    devtool: 'source-map',
    plugins: [

    ],
    module: {
        rules: [{
            test: /\.tsx?$/,
            loader: 'ts-loader',
            exclude: /node_modules/
        }]
    }
}
```

## 描画用のソース

[https://doc.babylonjs.com/](https://doc.babylonjs.com/)のトップにサンプルが置かれています。

（差分）
- 描画用のクラス(MySceneとしました)を別ファイルとし、app.jsでは描画用クラスの読み込みと初期化だけ実施しています。


```
import MyScene from './my-scene'
window.addEventListener('DOMContentLoaded', () => {
    // Create the game using the 'renderCanvas'.
    let game = new MyScene('renderCanvas');

    // Create the scene.
    game.createScene();

    // Start render loop.
    game.doRender();
  });
```

# おわりに

一通り作ってみてから、まあ、こういうのはいろんな人がやってるだろうな、、と思って検索してみたら、やはり複数件ありました。

Googleでの先頭3件くらいを以下に転記しておきます。

- [https://github.com/pandadelphin/babylonjs-typescript-webpack-starter](https://github.com/pandadelphin/babylonjs-typescript-webpack-starter)
- [https://github.com/deluvas/babylonjs-typescript-starter](https://github.com/deluvas/babylonjs-typescript-starter)
- [https://github.com/BeardScript/babylonjs-webpack-boilerplate](https://github.com/BeardScript/babylonjs-webpack-boilerplate)