ReScriptでReactのHelloWorld&ユニットテスト
概要
ReScript
とりあえず、ReScriptのみを扱うシンプルな新規プロジェクトを作成して、bs-jest
でテストを実行できるようにしてみます。
この記事では、ReScriptの公式手順を使わずに、NPMの素のプロジェクトを作成して、必要最低限のライブラリを指定してインストールしていきます。
- グローバルを汚さずににReScriptプロジェクトを作る方法
- ReScriptでReactを動かすまでの設定方法
bs-jst
を使ったテスト方法
の大枠が解ると思います。
ReScriptは、ReScriptのビルド設定など固有の設定をbsconfig.json
の中に記述します。
その内容によって、ビルドした結果が大きく変わってきます。
Reactだけではなく、SvelteからReScriptを利用したりする可能性も考え、ReScriptをmjs
ファイルとしてビルドして、さらにユニットテストの実行もES6のまま実行するようにします。
なお、Nodeはv14を前提としています。
プロジェクト作成
まずは、とりあえずReScript組み込みのJSXを使って簡単にReactアプリケーションを作ってみます。
なお、全てのライブラリは今回作成されるsamples
配下にインストールされるので、グローバル環境を汚すことはありません。
[koji:rescript]$ mkdir -p samples/src
[koji:rescript]$ mkdir -p samples/test
[koji:rescript]$ mkdir -p samples/public/script
[koji:rescript]$ mkdir -p samples/public/style
[koji:rescript]$
[koji:rescript]$ cd samples
[koji:samples]$ npm init
.envrc
自分はNode.jsの切り替えをenvrcで管理しています。
必要が有れば以下のような内容でプロジェクトディレクトリ内に.envrc
というファイル名で保存しておいて下さい。
export PATH=$HOME/opt/node/node-v14.15.4-linux-x64/bin:$PATH
ライブラリのインストール
npm install --save-dev bs-platform parcel@next @glennsl/bs-jest jest
npm install --save @rescript/react react react-dom bs-fetch
余談ですが、bs-platform
というライブラリは、近々rescript
に変更される予定のようです。分かりやすくなって良いですね。
必要なファイルの準備
ReScript/Reactに必要最低限なファイルを準備します。
bsconfig.json
プロジェクトルートにbsconfig.json
を作成し、以下のような内容にする。
{
"name": "samples",
"version": "0.0.1",
"sources":
[
{
"dir" : "test",
"subdirs" : true,
"type": "dev"
},
{
"dir" : "src",
"subdirs" : true
}
]
,
"package-specs": {
"module": "es6",
"in-source": false
},
"suffix": ".mjs",
"bs-dependencies": [
"@rescript/react",
"bs-fetch"
],
"ppx-flags": [],
"reason": { "react-jsx": 3 },
"bs-dev-dependencies": [
"@glennsl/bs-jest"
],
"warnings": {
"error" : "+101"
}
}
package.json
既に存在していますので、中身を修正します。
scripts
の中身は最低限以下のようにします。
"scripts": {
"clean": "npx bsb -clean-world",
"build": "npx bsb -clean-world -make-world && npx parcel build public/index.html",
"start": "npx parcel public/index.html",
"re:build": "npx bsb -make-world",
"re:watch": "npx bsb -clean-world -make-world -w",
"re:test": "NODE_OPTIONS=--experimental-vm-modules npx jest"
},
React
本命ですね。 とはいえ難しいことはありません。ReScriptはReactをとても良い感じに統合してくれています。
まず、src/Index.res
を作成します。
このファイルがReScriptアプリケーションの本体になります。
switch (ReactDOM.querySelector("#app")) {
| Some(app) => ReactDOM.render(<Application />, app)
| None => ()
}
次に、ReScriptでReactコンポーネントを作成します。
src/Application.res
と言うファイル名で、以下の内容を記述します。
@react.component
let make = () => {
<div> <h1> {`こんにちわReScript!`->React.string} </h1> </div>
}
public/index.html
public/index.html
を作成して、以下の内容にします。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<title>ReScript</title>
</head>
<body>
<div id="app"></div>
<script src="../lib/es6/src/Index.mjs"></script>
</body>
</html>
起動
この時点で、もしnpm run re:watch
を実行していないのであれば、実行して常にReScriptファイルをトランスパイルさせるか、npm run re:build
を都度実行してReScriptファイルをJavaScriptにトランスパイルさせて下さい。
トランスパイル出来たら、npm start
と実行すれば自動的に確認用サーバが起動して、ReScriptでReactアプリケーションが作成できたことが確認できます。
サーバはhttp://localhost:1234で起動します。
ユニットテスト(bs-jst)
jest.config.json
プロジェクトディレクトリ直下にjest.config.js
を作成して、以下のようにして下さい。
module.exports = {
testMatch: ["**/test/**/*.?(m)js"],
moduleFileExtensions: ["js", "jsx", "mjs"]
};
テストの作成
次に、test/SampleReScriptTest.res
と言うファイルを作成して、実際に以下のようなテストを書いてみます。
open Jest
open Expect
let () = describe(`テストのサンプル`, () => {
test(`最初のテスト`, () => {
expect(1) |> toBe(1)
})
// 複数のexpectを一つのテストで実行したい場合は以下のようにtestAllを使って、
// テスト対象になるデータを以下のようにlistで渡す。
testAll(`複数テスト`, list{1, 2, 3}, v => {
let value = switch v {
| 1 => v * 2
| 2 => v * 2
| _ => v * 2
}
expect(value) |> toBe(v * 2)
})
})
テストの実行
後は、package.json
に指定したスクリプトを実行するだけです。
npm run re:test
と実行すると以下のようにJestが実行されます。
[koji:samples]$ npm run re:test
> samples@1.0.0 re:test /home/koji/code/rescript/samples
> NODE_OPTIONS=--experimental-vm-modules npx jest
(node:13666) ExperimentalWarning: VM Modules is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
PASS lib/es6/test/SampleReScriptTest.mjs
テストのサンプル
✓ 最初のテスト (2 ms)
✓ 複数テスト - 1
✓ 複数テスト - 2
✓ 複数テスト - 3 (1 ms)
Test Suites: 1 passed, 1 total
Tests: 4 passed, 4 total
Snapshots: 0 total
Time: 0.678 s
Ran all test suites.
[koji:samples]$
まとめ
これで、ReScriptのプロジェクトをゼロから作成してReactを動かし、ユニットテスト(bs-jst)を実行する方法がわかりました。
テストを実行するために、NODE_OPTIONS=--experimental-vm-modules
というnodeのまだ正式に採用されていない機能を使う点がネックですが、コレを使えば今後Svelte等の他のフロントエンドフレームワークなどでも簡単にReScriptを利用することが出来るようになります。
ReScriptは元々はFacebook発のReasonmlという別の名称だったものが2020年末にリブランディングされたものです。 Reasonml時代は、「OCamlをベースとしたフロントエンド用関数型プログラミング言語」という面を強調していた面があったと個人的には思っていますが、ReScriptになってからは、意図的にOCamlや関数型プログラミングという単語は使わずに、「フロントエンド開発者を楽にさせる」という面を押し出している印象です。
とはいえ、OCamlベースの最強の型システムがあり、文法もOCamlとTypeScriptのちょうど中間のような感じになっているので、OCamlとTypeScrpitユーザ双方ともに学びやすい言語では、と思います。
今後、SvelteとReScriptを連携させる方法なども別途書いていきますが、2021年内にはReScript自体のチュートリアルを用意したいなーと思っています。
おまけのgitignore
*.exe
*.obj
*.out
*.compile
*.native
*.byte
*.cmo
*.annot
*.cmi
*.cmx
*.cmt
*.cmti
*.cma
*.a
*.cmxa
*.obj
*~
*.annot
*.cmj
*.bak
lib/bs
lib/ocaml
*.mlast
*.mliast
.vscode
.merlin
.bsb.lock
/node_modules/
*.bs.js
/src/**/*.mjs
/test/**/*.mjs
.envrc
.cache/
dist/
yarn-error.log
公開日:2021/04/19