TypeScriptによるバックエンドとフロントエンドの両面開発

# TypeScriptによるバックエンドとフロントエンドの両面開発


　※全てをTypeScriptで記述した[ツリー型情報掲載システム](https://ttis.croud.jp/)を運用中です

## １．言語の選択

　Web開発を一つの言語で行おうと思った場合、事実上の選択肢は素のJavaScriptを使うか、AltScript系を使うことになります。

　前者のJavaScriptは気軽にコーディングできる反面、気付かぬうちに危険なコードが混入します。JavaScriptは仕様をきっちり把握していればある程度回避できますが、実は地雷原をサンダルで散歩するに等しい言語なのです。今日は無事でも、明日は足が吹っ飛ばされるかもしれません。

　JavaScriptの危険性を回避するにはAltScript、中でも急速に伸びているTypeScriptを強くお勧めします。TypeScriptが一つ使えれば、フロントエンドとバックエンド両方が同じ言語で、しかもある程度の安全を担保した状態で開発出来るのです。

## ２．TypeScriptによる両面開発の利点

- 同じ文法なので効率が上がる  
例えばバックエンドをPHP、フロントエンドをJavaScriptで開発したケースです。この二つの言語、文法が似ています。似ているが故に同時開発すると、拡張for文などでミスります。PHPでfor-inを使おうとしてしまったりと、一瞬で気が付くミスですが、けっこうやってしまいがちです。完全に同じ文法の言語を使えば、こういった部分でのストレスがありません。

- ソースコードが使いまわせる  
　フロントエンドとバックエンドで同じような処理を書く場合があります。言語が違えばいちいち書き直しですが、同じ言語ならコピペで終了です。共通ライブラリとして整備しておけば、コピペの必要すらありません。

- データのやり取りが楽  
　TypeScriptなら型が組めるわけですが、同じ言語ならこの型が共通化できます。特に威力を発揮するのは通信部分です。バックエンドとフロントエンドの通信は、Ajaxを用いた非同期通信を用います。やりとりの標準的な方法では、いったんJSON形式を通してパースし、お互いの終端でデコードして使います。TypeScriptなら、このデコード後の型が共通化できるのです。これが出来るか否かで、開発効率がまったく変わってきます。感覚的にはローカルファンクションを呼び出す感覚で通信が可能となるのです。

## ３．両面開発で気を付けるべきこと

### 3.1 開発環境の設定

　VSCodeなどの開発環境は、TypeScriptの文法チェックをするときに**tsconfig.json**を参照します。この設定値を元にチェック項目を判断するわけです。当然ですがバックエンドとフロントエンドでこの設定値が異なります。特に入出力ディレクトリは確実に異なった設定になるので、きっちり区別をつけておかないと、大量のエラーに悩まされることになります。

　まず最初にやらないといけないのは、プロジェクトルートのディレクトリに配置する**tsconfig.json**です。

```tsconfig.json
{
  "exclude": [
    "."
  ]
}
```

　これを置いておかないと、全てのディレクトリの**.ts**が混合でチェックされてしまうので悲惨なことになります。これを配置したら、あとはフロントエンド用とバックエンド用のディレクトリそれぞれに**tsconfig.json**を作ればOKです。コンパイル時、手動でそれぞれコンパイルするなら

```.sh
tsc -b configファイルのパス
```

とします。

　また、異なるtsconfig.jsonをトップのtsconfig.jsonから呼び出すこともできます。

```tsconfig.json
{
  "references": [
    {
      "path": "フロントエンドパス"
    },{
      "path": "バックエンドパス"
    }
  ],
  "exclude": [
    "."
  ]
}
```

としておけば、

```.sh
tsc -b
```

だけで、両方同時にビルドすることができます。ただし、フロントエンドはWebPackなどのモジュールバンドラを使うケースが多いのでその場合、ここに記述するのはバックエンドの参照のみになります。また、参照を受け付ける場合は、参照先の設定に

```tsconfig.json
{
  "compilerOptions": {
    "composite": true
  }
}
```

を入れておく必要があります。

### 3.2 出来ることの違い

　バックエンドはファイルの入出力やDBアクセスなど、一通り何でもできます。ただしDOM操作などは標準対応しておらず、自分で組むか、jsdomのようなパッケージをnpmからとってくる必要があります。

　フロントエンドはDOM操作が標準でできますが、当然ファイル操作などは出来ません。ブラウザ内で許可されているlocalstrageを使ったり、バックエンドに入出力要求する必要があります。

　ということで使用可能なAPIはまったく異なるので、ここだけはきちんと区別して開発しなければなりません。

## ４．最終的な開発環境とビルド手順

　現在私の開発方法はフロントエンドにWebPack、バックエンドにtscという形で行っています。tscの方は参照設定で複数のプロジェクトを一コマンドでコンパイル出来るのですが、WebPackにはプロジェクトの参照設定がないので、ちょっと面倒くさいことになっています。

- tsc - バックエンドメインプロジェクト - Active-Module-Framework  
- WebPack - フロントエンドメインプロジェクト  
- WebPack - JavaScript-Window-Framework  

　バックエンドはActive-Module-Frameworkというオレオレフレームワークを使っており、バックエンドのメインプロジェクトとは独立させた構成になっています。tscは参照設定を使うことによって、この異なるプロジェクトの同時ビルドが可能です。

　フロントエンドはJavaScript-Window-Frameworkというオレオレフレームワークを使っており、フロントエンドのメインプロジェクトとは独立させた構成になっています。WebPackには参照設定がないので、フロントエンドのビルドには、WebPackを二回立ち上げます。-wオプションを入れて監視ビルドさせるので、最初にそれぞれ一回起動する手間があるだけなのですが、やっぱりちょっと面倒くさいです。

## ５．利点は大きいが移行するまでの壁も大きい

　TypeScriptによる両面開発は数々のメリットがある反面、壁が大きいのも確かです。まずNode.jsの非同期処理に慣れるまでそれなりに時間がかかります。これは素のJavaScriptでも同じですが、他の言語には無い特徴故に慣れるまでに時間を要します。さらにTypeScriptの型の扱いも、ケースごとにどう対処するのかという知識を蓄積するまでに、多少の時間をとられます。この壁を乗り越えた先にたどり着けるかどうかは、各々のやり方次第です。しかしWeb開発という面に限って言えば、とても大きな効率化を図ることが出来るのです。