Visual Studio 2017でCordova+Typescript+React(JSX)の最小構成

情報が古くなったり、誤りがあったりするため、訂正&加筆いたします。

#**1.Visual Studio 2017のCordova**
CordovaはHTML+CSS+JavaScriptといったWeb技術でクロスプラットフォームのネイティブアプリ開発を可能にしたツールです。VS2013からプレビューバージョンでサポートし始めて、VS2017では標準でTypeScriptのCordovaアプリを作れるようになっています。早速骨格をつくりました。
![solution_explorer.png](https://qiita-image-store.s3.amazonaws.com/0/143365/31782fb7-b9d7-36a4-6907-a6f6b52fac09.png)

#**2.Reactjsをインストール**

プロジェクトルートにあるpackage.jsonにReactの記載を追加

```package.json
...
  "dependencies": {
    "react": "15.4.2",
    "react-dom": "15.4.2",
  },
...
```
バージョンは2017年時点の最新版です、package.jsonを保存すると、自動的にインストールが発動するようになっています。

#**3.reactのtype定義を追加**
Node.js自体は使いませんが、typingsを取得するためパッケージマネージャのnpmが必要なのでNode.jsをインストール
https://nodejs.org/en/download/

typescriptを採用したため、reactの型定義ファイルをインストール、--saveオプションをつけると、package.jsonに記載される。ちなみに、先にpackage.jsonに記載しておいて保存でinstallをキックするやり方ももちろんOK。

```npm install @types/react --save```
```npm install @types/react-dom --save```

「node_modules」の下に「@type」フォルダにインストールされました。

#**4.TypeScriptでJSX/TSXコンパイルするための設定**
tsconfig.jsonに下記記載を追加する

```tsconfig.json
    "module":"commonjs",
    "jsx": "react",
    "target": "es5"
```
###"module":"commonjs"
commonjsのモジュール解決方式に準拠すること、import/exportと書いたコードは後のwebpackやbrowserfyなどのモジュール解決ツールによってバンドルできるようにコンパイルされる、ほかには"amd"(requireJS方式)、"umd"（commonJSとrequireJS両方対応）、"none"(いわゆるスタンダーロンJS)などがある。
###jsx:react
React.createElement()のようなネイティブReactコードに変換するためです。
###target:es5
多くのブラウザがサポートしている「ECMAScript5」に準拠したJavaScriptにコンパイルするための設定です。

#**5.tsxファイルの作成**
いよいよ本題のreactを書きます。以下に簡単な参照を示す実装例です。プロジェクト直下の「Scripts」フォルダー(場所は任意です)で「追加」→「新しい項目...」から選択できます。

```MyComponent.tsx
import * as React from "react";

export interface HelloProps { compiler: string; framework: string; }

export default class Hello extends React.Component<HelloProps, any> {
    render() {
        return <h1>Hello from {this.props.compiler} and {this.props.framework}!</h1>;
    }
}
```

```App.tsx
import * as React from "react";
import * as ReactDOM from "react-dom";
import Hello from "./MyComponent";

ReactDOM.render(
    <Hello compiler="TypeScript" framework="React" />,
    document.getElementById("example")
);
```
tsconfig にcompileOnSaveをOnにすれば、保存時にJavaScriptにコンパイルされ、「www/scripts」に出力されます。次はIndex.htmlを編集します。実行時のReactライブラリの調達方法いくつがありますが、ここではCDNを使います。

```Index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
</head>
<body>
    <div id="example"></div>

    <!-- Dependencies -->
    <script src="https://fb.me/react-15.2.1.js"></script>
    <script src="https://fb.me/react-dom-15.2.1.js"></script>

    <!-- Main -->
    <script src="./scripts/app.js"></script>
</body>
</html>
```

先ほどのapp.jsをロードするように記載し、無事ビルドが通りますが実行してみると、F12開発者ツールで
```var React = require("react");```
あたりに「require is not defined」というエラーがでてました。requireとはNodeJSのモジュールロードシステムでブラウザに存在しない仕組みです。ここでブラウザで理解できるようにモジュールの依存を解決しないといけない、2017当時はwebpackをチョイスしました。2018に入り一時Parcelが勢いを増しましたが、webpackも多くの改良を重ね、HotReloadや分割bundleあたりのノウハウも蓄積できたので、当面webpackを採用していきたいと思います。


#**6.Webpackの導入**
Webpackをインストール、-gをつけるかどうかそれぞれの事情で決めてもいいです。
```npm install -g webpack```
もし個別プロジェクトに入れたい場合は、devDependencyに追加するのは妥当でしょう。
```npm install --save-dev webpack```
webpackを動かすためにはwebpack.config.jsをプロジェクトルールパスに追加する必要があります。

config例：

```webpack.config.js
module.exports = {
  "entry": "./www/scripts/app.js",//⇒入力js、エントリjsだけでよい
  "output": {
    "filename": "./www/scripts/bundle.js"//出力js
  },

  "devtool": "source-map",

  "resolve": {
    "extensions": [ "", ".webpack.js", ".web.js", ".js" ]
  },

  "module": {
    "loaders": [
       {
        "test": "/\\.tsx?$/",
        "loader": "ts-loader"
      }
    ],
    "preLoaders": [
      {
        "test": "/\\.js$/",
        "loader": "source-map-loader"
      }
    ]
  },
  "externals": {
    "react": "React",
    "react-dom": "ReactDOM"  //依存ライブラリをbundleから除外する
  }
};
```
上記設定では、Reactなどのサードパーティライブラリをbundleしないようになっている例です。
これはライブラリを毎回バンドルされる必要がなく、開発効率の観点でいいとされるが、これで別途webpackでバンドルしたReactパッケージをロードするか、CDNで調達する必要があります。


webpackのパスを通して、webpack.config.jsのパスに移動し下記コマンドを実行
```webpack```
指定したところにbundle.jsが出力されるので、これをscriptタグの参照に追加します。

```Index.html
...
    <!-- Main -->
    <script src="./scripts/app.js"></script>
...
```
これで「Hello from TypeScript and React!」が表示されればとりあえずこれでReactのワークスールを一通り完了です。