Leiningen re-frame Intellij IDEA の環境でREPLの実行、ソース編集時のホットリロードがブラウザに反映されるのを確認するまで


## 動機

Clojure触るのが面白く、REPLでの体験がすばらしいのでこれでフロントエンドの開発も面白いのではとClojureScriptに入門したく以下の記事を写経させていただこうと始めたところ

[ClojureScript/re-frame開発における思考フロー](https://qiita.com/lagenorhynque/items/3770e520bee0007e417c)

動作確認環境をIntellijで設定して動かすのに少し苦労しました。同じような悩みがある人がでるかもしれないから書いておこうという思いで書きます。

## この記事で扱うこと

leinのコマンドで以下を行う。

- IntellijでREPLで<b>shadow-cljs</b>を動かしてブラウザとつながることを確認する。
- ソースのホットリロードができることを確認する。

以上をwatchモードで行う。
テストだけnodeのコマンド(npx) でwatchする。

## 対象

- Clojureを完全に理解している。(仕事などで書いたことなく、初級者レベル)
- JavaScript全然わからない。(仕事でまああま書いたことある)
- どうやらClojureでフロントエンドがかけるらしい。
- reagentというreactのラッパーがあるらしい。
- re-frameというreagentのフレームワークがあるらしい。
- shadow-cljsというビルドツールがあるらしい。
- でも色々な記事調べたら設定がめんどくさそう。
- emacs, spacemacs使えない。
- Jet BrainsのIDEに慣れている。それでできないの？

## 前提と準備

この記事は以下の環境で確認しています。

- Java 8, もしくは11がインストールされている。(この2つで動作を確認しています。)
- Clojureがインストールされている。
- leiningenがインストールされている。
- node.jsがインストールされている。
- Intellij IDEAがインストールしている。
- Cursiveプラグインが入っている。
- File Watcherプラグインが入っている。
- Intellij IDEAでTerminalプラグインでSwitch Focus to Editorのショートカットに ESCを設定している。(terminal, REPLとエディターを頻繁にいききするので)

Mac で動かしましたが、Windowsでもleiningenが動作するのを確認しているので同じ設定で動くと思います。また今回の記事をあたり、Intellij のCE版（普段はUlitimateを使っているので）をダウンロードしてそれを使って動作確認しました。

Intellijのterminalの設定で
Preferences > Tools > Terminal > Override IDE shortcuts
のチェックを外す設定をしておくのがおすすめです。

- [Shortcut to switch between editor and terminal?]
(https://intellij-support.jetbrains.com/hc/en-us/community/posts/115000166250-Shortcut-to-switch-between-editor-and-terminal-)


もしあなたがClojureを触り始めたばかりでIntellijで触ったことがない場合、以下の記事を参考にしてください。非常に参考になります。特に構造編集に関しては知る知らないでClojureへの印象が変わります。

- [IntelliJ IDEA と Cursive で始める -Clojureの日本語ガイド]
(https://www.notion.so/isamushimada/leiningen-re-frame-Intellij-IDEA-REPL-9a794f27e36543e4acc4a6008ebae5e4#6656501984e544069bfa8500fd59466e)
- [Clojure開発環境での基本操作まとめ: Spacemacs, IntelliJ IDEA (Cursive), VS Code (Calva), rebel-readline](https://qiita.com/lagenorhynque/items/0b52575e90bad563e4bd)

File Watcherについて、長い間Intellijでホットリロードを反映させる場合、terminalにフォーカス(terminalに切り替え)をあてないと反映されないと思っていました。以下の記事を参考にでFile Wacherを使用するようにしたところいちいちフォーカスあてずに反映されるようになりました。

- [Clojure開発環境でのリンターclj-kondo, Joker設定まとめ: Spacemacs, IntelliJ IDEA (Cursive), VS Code (Calva)](https://qiita.com/lagenorhynque/items/dd9d6a1d97cbea738bc0)


## 本題

以下のre-frameのリポジトリで紹介してあるテンプレートを使います。

re-frame-templete
[https://github.com/day8/re-frame-template](https://github.com/day8/re-frame-template)
以下のように書かれてあるので

```
lein new re-frame <app-name>
```

今回はアプリ名をsample-appとして実行します。

```
lein new re-frame sample-app
```
これでプロジェクトの雛形が作られます。生成されたREADME.mdにアプリの立ち上げ方、テストの実行方法など書いてくれています。

ここでIntellijを立ち上げて以下の<i>open or Import</i>
で先ほど作ったプロジェクトを指定します。

![14.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136265/628fc326-93a5-88c4-1612-5d6fa4fd49e7.jpeg)

もし既にほかのプロジェクトを開いていて(たとえばAPPのサーバープロジェクトを開いているなど)上記画面から選べない場合は
以下の流れで開いてください。

<details>
<summary>すでに他のプロジェクトを開いている状態から開く場合</summary>
<div>

File > New > Project from existing sources..を選びます。
ここで作成したプロジェクトを指定します。
Import project from external model > Leiningenを選んでNext> Next > Next
SDKを選ぶところになるのでJava 1.8かそれ以降を選んでください。私は11で確認しています。

</div>
</details>

プロジェクトが開きます。
この時点ではnode_moduleは作成されていません。

ここでプロジェクト内に生成されたREADME.mdに Running the App
``` lein watch ```とあるので実行します。

```
➜  sample-app lein watch
lein-shadow - reading NPM dependencies from .../sample-app/src/cljs/deps.cljs
lein-shadow - running: npm --version
lein-shadow - NPM version 6.14.7
lein-shadow - running: npm install --save-dev --save-exact shadow-cljs@2.10.19 karma@5.1.0 karma-chrome-launcher@3.1.0 karma-cljs-test@0.1.0 karma-junit-reporter@2.0.1
lein-shadow - NPM install successful + shadow-cljs@2.10.19+ karma-cljs-test@0.1.0+ karma-junit-reporter@2.0.1+ karma-chrome-launcher@3.1.0+ karma@5.1.0updated 5 packages and audited 272 packages in 2.653sfound 0 vulnerabilities
lein-shadow - running shadow-cljs...
shadow-cljs - HTTP server available at http://localhost:8280
shadow-cljs - HTTP server available at http://localhost:8290
shadow-cljs - server version: 2.10.19 running at http://localhost:9630
shadow-cljs - nREPL server started on port 8777
shadow-cljs - watching build :app
shadow-cljs - watching build :browser-test
[:app] Configuring build.
shadow-cljs - watching build :karma-test
[:browser-test] Configuring build.
[:karma-test] Configuring build.
[:karma-test] Compiling ...
[:app] Compiling ...
[:browser-test] Compiling ...
[:browser-test] Build completed. (226 files, 225 compiled, 0 warnings, 35.81s)
[:karma-test] Build completed. (146 files, 146 compiled, 0 warnings, 28.08s)
[:app] Build completed. (527 files, 526 compiled, 0 warnings, 36.69s)
```
ここで必要なものも一緒にインストールされるようです。node_moduleもここで作成されます。この時点で```http://localhost:8280```でアクセスできるようになります。

<details>
<summary>プロセスを終了する場合</summary>
<div>
終了はCtrl + C(macの場合）です。もしプロセスを落とさずにIntellijを終了し、ふたたび```lein watch```すると
既にportが使われているエラーになるので以下のようにしてkillしてから実行してください。

``` 
> lsof -wni tcp:8280 
上記実行しpid確認。pidを指定してkill
> kill -9 pid
```
</div>
</details>

## REPL

REPLの設定をしていきます。

IDEの上のほうにあるconfigureの設定で
![18.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136265/14e09b38-1612-8d2d-58fb-bd5f23cb2b2f.jpeg)

プラスボタンから Clojure REPL > Remote を選び右側のペインで
Connection type > nREPL
Connection details > Use port from nREPL file > Project > sample-app
にします。
![16.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136265/ee764c04-42f5-dc4d-c606-2856b72e9163.jpeg)
ここでOKを押下します。

configure にスタートボタン?が出たと思うのでこれを押下します。これでREPLが立ち上がると思います。
立ち上がったら以下のコマンドを打ちます。
<i>参考</i>
[ClojureScript IntelliJ IDEA and shadow-cljs]
(https://andrearichiardi.com/blog/posts/clojurescript-cursive-shadow-setup.html)

```clojure
;; 引数の :app は project.clj の:shadow-cljs :buildsにあるキーです。
(shadow/REPL :app)
```

これを打つとREPLの右上のプルダウンがcljからcljsに変化すると思います。
![shawod-REPL.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136265/efeed06a-f98f-674e-cdc9-28a53bc04b3a.jpeg)

この時点でブラウザとつながっています。
では試していきます。

### REPL上でcljsを実行

REPL上で
``` (js/alert "hello world") ```打ちます。するとブラウザにアラートが出ます。

![helloworld.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136265/5e71092c-0666-ed0e-cf51-5e91126377b9.gif)

またREPL上でブラウザに表示されているDOMにアクセスして値を取得することもできます。

```clojure
 (-> (.querySelector js/document "#app div h1") .-textContent) 
;; => Hello from re-frame
```

![getDom.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136265/83888142-bd8c-7a47-ad7b-198b864313fa.gif)

### ホットリロードの確認

File Watcherでファイルの変更をIDEで監視されていればソースを変更するたびにブラウザに反映されます。

![renderDom.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136265/c786015a-81e3-007b-bf62-91b8d67a4bef.gif)

### TEST
README.mdに書いてありますが
IDE のterminalで＋を押して別ウィンドウでterminalを開き

```
npx karma start
```
と打ちます。
ファイル変更が検知されてtestが実行されるようになります。

![test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136265/e762bee7-ffa9-e2ba-5c77-812c0a3095d9.gif)

以上です。

## まとめ

- Clojure関連の情報を書いてくれている方々の環境はemacs,spacemacs,vimが多いようでIntellijで実行するとき戸惑うときもあるがやはりIntellijでも簡単に実行はできる。
- Clojureの話題は英語が多い中、英語が苦手な私のような人でもClojure書きたい人もいるので有用な記事を書いてくれている人に感謝。

## 参考にしたもの

- [ClojureScript/re-frame開発における思考フロー](https://qiita.com/lagenorhynque/items/3770e520bee0007e417c)
- [Shortcut to switch between editor and terminal?]
(https://intellij-support.jetbrains.com/hc/en-us/community/posts/115000166250-Shortcut-to-switch-between-editor-and-terminal-)
- [IntelliJ IDEA と Cursive で始める -Clojureの日本語ガイド]
(https://www.notion.so/isamushimada/leiningen-re-frame-Intellij-IDEA-REPL-9a794f27e36543e4acc4a6008ebae5e4#6656501984e544069bfa8500fd59466e)
- [Clojure開発環境での基本操作まとめ: Spacemacs, IntelliJ IDEA (Cursive), VS Code (Calva), rebel-readline](https://qiita.com/lagenorhynque/items/0b52575e90bad563e4bd)
- [https://github.com/day8/re-frame-template](https://github.com/day8/re-frame-template)
- [Clojure開発環境でのリンターclj-kondo, Joker設定まとめ: Spacemacs, IntelliJ IDEA (Cursive), VS Code (Calva)](https://qiita.com/lagenorhynque/items/dd9d6a1d97cbea738bc0)
- [ClojureScript IntelliJ IDEA and shadow-cljs](https://andrearichiardi.com/blog/posts/clojurescript-cursive-shadow-setup.html)
- [Clojure/ClojureScript関連リンク集](https://qiita.com/lagenorhynque/items/68c314c288b75a9492ba#%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83)