CentOS7系にNode.js8系、Flow、Webpackをインストールして動かすまで


# Flowとは

**Flow**はFacebookが開発している、JavaScriptの静的型チェックのツールです。
JavaScriptの型チェックとしては、**TypeScript**が有名です。

ただ、普通のjsで書かれた既存プロジェクトにTypeScriptを導入するのは、それなりに労力がかかります。

一方、Flowの場合はファイルの先頭に `// @flow` と書かれたファイルだけをチェック対象と出来るため、既存プロジェクトへの導入が容易な点も魅力です。

https://flow.org/

# 本記事でやること
Node.jsのインストールから始めて、実際にFlowを実行できる環境を作成し、jsファイルにチェックをかけてみます。
その後、Webpackを使い、型定義を除外してバンドルするところまでやってみます。

# 環境
- CentOS 7.2
- Node.js v8.9.4
- flow 0.72.0
- webpack 4.8.3

# ディレクトリ構成
最終的なディレクトリ構成は以下のようになります。

```
$ tree -a -L 1
.
├── .babelrc
├── .flowconfig
├── Human.js
├── dist
├── index.js
├── node_modules
├── package-lock.json
├── package.json
└── webpack.config.js
```

# Node.jsのインストール

以下の手順を参考にNode.jsのインストールを行います。

https://nodejs.org/en/download/package-manager/#enterprise-linux-and-fedora

```
$ curl --silent --location https://rpm.nodesource.com/setup_8.x | sudo bash -
$ sudo yum install -y nodejs gcc-c++ make
```


# プロジェクトの作成

まずはプロジェクトを作り、必要なパッケージをインストールします。
`cd $_` と入力すると作成したディレクトリに移動することが出来ます。

```
$ mkdir flowtest && cd $_
$ npm init -y
$ npm install --save-dev babel-cli babel-loader babel-preset-env babel-plugin-transform-flow-strip-types flow-bin webpack webpack-cli
```

# jsファイルの作成

flowで型チェックをしたいjsファイルを作ります。どちらもファイルの先頭に `// @flow` を記載します。

## Human.js
```
// @flow

export default class Human {
  name: string;
  constructor(name: string) {
    this.name = name;
  }

  hello() {
    return `Hi! I'm ${this.name}.`;
  }
}
```

## index.js
```
// @flow

import Human from './Human';

let sato: Human = new Human('sato');
let members: Human[] = [sato];
let suzuki: Human = new Human('suzuki');
members.push(suzuki);

for (let m: Human of members) {
  console.log(m.hello());
}
```


# flowの実行

最初にinitをして`.flowconfig`という設定ファイルを作ります。

```
$ npx flow init
```
npm5.2.0から導入された `npx` コマンドを使うと、npmでインストールしたパッケージを簡単に実行することが出来ます。
古いバージョンであれば、 **\`(npm bin)\`** と書くことで、 `node_modules/.bin` を出力してくれますので、 以下のコマンドで実行可能です。

```$ `(npm bin)`/flow init```

次に、`.flowconfig` を開き、ignoreセクションに以下を記述し、node_modulesは対象外とします。

```
[ignore]
.*/node_modules/.*
```

それではflowを実行します。

```
$ npx flow
Launching Flow server for /home/vagrant/flowtest
Spawned flow server (pid=4804)
Logs will go to /tmp/flow/zShomezSvagrantzSflowtest.log
Monitor logs will go to /tmp/flow/zShomezSvagrantzSflowtest.monitor_log
No errors!
```

問題なく終了しました。

エラーを発生させるために、Human.jsのconstructorの**name変数**の型を、**string**から**int**に変えてみます。

```
  constructor(name: int) {
    this.name = name;
  }
```

再度flowを実行すると、以下のようにエラーが出ることが分かります。

```
$ npx flow
Error ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ Human.js:5:21

Cannot resolve name int.

     2│
     3│ export default class Human {
     4│   name: string;
     5│   constructor(name: int) {
     6│     this.name = name;
     7│   }
     8│


Found 1 error
```

# webpackの実行
webpackを実行する前に、`.babelrc` と`webpack.config.js`を作成します。

envの指定は、よくある**babel-preset-env**の書き方です。
https://babeljs.io/docs/plugins/preset-env/

**transform-flow-strip-types** がソースコードの型定義部分を取り除いてくれます。
https://www.npmjs.com/package/babel-plugin-transform-flow-strip-types

## .babelrc

```
{
  "presets": [
    ["env", {
      "targets": {
        "browsers": ["last 2 versions", "safari >= 7"]
      }
    }]
  ],
  "plugins": ["transform-flow-strip-types"]
}
```

## webpack.config.js

```
module.exports = {
  mode: 'development',
  entry: './index.js',
  output: {
    path: `${__dirname}/dist`,
    filename: 'main.js'
  },
  resolve: {
    extensions: ['.js']
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      }
    ]
  }
};

```

それではwebpackを実行します。

```
$ npx webpack
Hash: e401b171025fd6fe3bd6
Version: webpack 4.8.3
Time: 465ms
Built at: 2018-05-20 15:13:13
  Asset     Size  Chunks             Chunk Names
main.js  5.1 KiB    main  [emitted]  main
Entrypoint main = main.js
[./Human.js] 1.07 KiB {main} [built]
[./index.js] 907 bytes {main} [built]
```


できあがったjsを、実際にターミナル上で動かしてみましょう。

```
$ npx babel-node dist/main.js
Hi! I'm sato.
Hi! I'm suzuki.
```


簡単にコマンドを実行できるよう、**package.json** に `npm scripts' を記載をしておきます。
**scripts**と書かれた部分を以下のように変更します。

```
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "check": "flow",
    "build": "flow && webpack"
  },
```

`npm run check`でflowが実行でき、`npm run build` でflowを実行後に問題がなければwebpackが実行されます。