Flowとは
FlowはFacebookが開発している、JavaScriptの静的型チェックのツールです。
JavaScriptの型チェックとしては、TypeScriptが有名です。
ただ、普通のjsで書かれた既存プロジェクトにTypeScriptを導入するのは、それなりに労力がかかります。
一方、Flowの場合はファイルの先頭に // @flow
と書かれたファイルだけをチェック対象と出来るため、既存プロジェクトへの導入が容易な点も魅力です。
本記事でやること
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のインストールを行います。
$ 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が実行されます。