three.jsのプロジェクトを作ってGitHubにあげてHerokuに公開するまでのステップ 2/2

Blenderで鉛筆のモデルとアニメーションを作ったので、three.jsを使用してwebブラウザに表示させたものをHerokuにアップしてみようと思います。
GitHubのリポジトリ作成から環境構築、Herokuのデプロイまでを備忘録として記載します。

今回の記事では、実際にthree.jsでシーンを作成〜Herokuのデプロイまでを行います。
それ以前の手順は以下の記事に記載しています。
[three.jsのプロジェクトを作ってGitHubにあげてHerokuに公開するまでのステップ 1/2](https://qiita.com/kyk_nr/items/ec3a0cb3e2b2004cc5e9)

# もくじ
[1. three.jsシーンの作成する](#1-シーンの作成)
[2. Herokuにデプロイする](#2-デプロイする)

#1. シーンの作成
three.jsにBlenderで作成したモデルを取り込み、ブラウザに表示させます。

:::note warn
この記事ではthree.jsやBlenderでのモデルの作成方法は記載していません。
:::

## (1) staticフォルダに必要なファイルを配置する
[前回](https://qiita.com/kyk_nr/items/ec3a0cb3e2b2004cc5e9)作成したstaticフォルダに以下のファイルを配置します。

* Blenderで作成したモデル
* draco（上記のモデルをDracoという方式で圧縮したので読み込む際に必要。）

dracoはnode_modulesのthreeの中にあるフォルダをstaticにコピペします。
`node_modules > three > examples > js > draco`
![shot1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604689/25fe8197-352f-5bfc-79f1-0022c9135606.png)

このようなフォルダ構成になります。
![shot2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604689/0f28a881-8ded-9e95-4001-876fd44af8bf.png)

## (2) three.jsでモデルを読み込みアニメーションさせる
前回と変更した部分を絞ってソースを紹介します。
ソースの全体は[GitHubのリポジトリ](https://github.com/kyoko-nr/pencil-animation)で確認できます。

```js:index.js
// Loaderをインポートする
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'

// Loader
const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath('/static/draco/') // サーバにあげた際のディレクトリを指定する
const gltfLoader = new GLTFLoader()
gltfLoader.setDRACOLoader(dracoLoader)

// Model
let mixer = null
gltfLoader.load(
  '/static/pencil_merged_animate.glb',
  (gltf) => {
    mixer = new THREE.AnimationMixer(gltf.scene)
    const action = mixer.clipAction(gltf.animations[0])
    action.play()
    gltf.scene.scale.set(0.5, 0.5, 0.5)
    gltf.scene.position.set(0, -1, 0)
    scene.add(gltf.scene)
  }
)

// Test cube もういらないので削除
// const cube = new THREE.Mesh(
//   new THREE.BoxGeometry(1, 1, 1),
//   new THREE.MeshNormalMaterial()
// )
// cube.rotation.set(0.3, 0.3, 0)
// scene.add(cube)

// Lights
const ambientLight = new THREE.AmbientLight(0xffffff, 0.8)
scene.add(ambientLight)

const dirLight = new THREE.DirectionalLight(0xffffff, 1.5)
dirLight.position.set(0, 0, 6)
scene.add(dirLight)

// Animate
const clock = new THREE.Clock()
let previousTime = 0
const tick = () => {
  const elapsedTime = clock.getElapsedTime()
  const deltaTime = elapsedTime - previousTime
  previousTime = elapsedTime

  if(mixer) {
    mixer.update(deltaTime)
  }

  renderer.render(scene, camera)
  window.requestAnimationFrame(tick)
}

tick()
```

ついでに背景を黄色にしてみます。

```css:style.css
.webgl
{
    position: fixed;
    top: 0;
    left: 0;
    outline: none;
    background-color: #FFDB46;
}
```

## (3) 前回コメントアウトしたCopyWebpackPluginを復活させる
前回動作確認のためにコメントアウトしたプラグインのコメントアウトを外します。

```js:webpack.config.js
// staticフォルダの中をコピーして展開してくれる
new CopyWebpackPlugin({
  patterns: [
    { from: path.resolve(__dirname, './static'), to: path.resolve(__dirname, 'dist/static') }
  ]
}),
```

## (4) 動きを確認する

```shell
yarn serve
```

上記のコマンドでローカルサーバを立ち上げるとアニメーションが表示されます。
<font color="grey">※ Macの場合はCommand + C、Windowsの場合は Ctrl + C でローカルサーバを停止できます。</font>
![ezgif.com-gif-maker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604689/4192ec6b-f863-55e0-5aad-b5ab945df3d1.gif)


#2 デプロイする

作成したthree.jsのプロジェクトをHerokuにデプロイします。

## (1) Herokuにプロジェクトを作成する

まずはログイン。

```shell
heroku login
```

プロジェクトを作成します。

```shell
heroku create {プロジェクトの名前}
```

プロジェクトが作成されると、コンソールにHerokuのプロジェクトのurlが表示されます。
そのurlを開くと以下のような画面が表示されます。
![shot3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604689/09b18502-c5f0-e75a-1ddf-5e7875df759d.png)

## (2) リモートリポジトリを登録
Herokuのリモートリポジトリを登録します。

```shell
heroku git:remote --app {プロジェクトの名前}
```

## (3) Node.jsで動かすための設定

Heroku上ではNode.jsでアプリを動かすため、エントリーポイントとなる「server.js」を作成します。
まずはexpressをnode_modulesにインストールします。

```
yarn add express
```

アプリを動かすためのコードを記述したserver.jsを作成します。

```js:server.js
const express = require('express'); // 先ほどインストールしたパッケージ
const serveStatic = require('serve-static');
const app = express();
app.use(serveStatic(__dirname + "/dist")); // buildした後に作成されるフォルダ名 = dist
const port = process.env.PORT || 8000; // port番号は適宜変更してください
app.listen(port);
console.log('server started '+ port);
```

package.jsonにHerokuでアプリを動かす際のコマンド（start）を追記します。

```json:package.json
"scripts": {
  "start": "node server.js",
  "serve": "webpack-dev-server",
  "build": "webpack"
}
```

以下のコマンドを実行した後、 **localhost:8000(server.jsで指定したポートNo)** にアクセスしてアプリが表示されるか確認します。

```
yarn start
```

## (3) Herokuにデプロイ

設定が完了したら、以下のコマンドgit経由でHerokuにデプロイします。

```shell
git add .
git commit -m "deploy to heroku"
git push heorku master
```

デプロイが完了したらHerokuのページから[Open app]のボタンで実際にアプリを見てみます。
![shot5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604689/ddf01723-b351-49a9-eb32-624d78216f1b.png)

無事表示されました！
![shot6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604689/501f033d-cdb7-56c5-509f-95a8fdfc8723.png)


# 参考にした記事

https://qiita.com/kottyan/items/dbc1edb82e8562235fac

https://www.pluralsight.com/guides/deploying-to-heroku-with-webpack