Stimulus controllerの登録方法の違い

# はじめに

Railsでstimulusを使う場合は、[stimulus-rails](https://github.com/hotwired/stimulus-rails) gem が使われます。
stimulus-rails gemの大まかな機能は以下です。
- Stimulus インストーラー
- Stimulus controller ジェネレーター

このジェネレーターで生成される stimulus controllerの登録方法は、JavaScriptの管理方法で違いがあります。
その違いについて、まとめます。

# 登録方法

stimulus-rails gemは、JavaScriptの管理方法として以下をサポートしています。
- JavaScript bundler
- Import maps

この管理方法によって、stimulus controllerの登録方法が違います。
それぞれの登録方法について以下に記します。

## JavaScript bundler

JavaScript bundlerを使っている状態で、`bin/rails stimulus:install`を実行すると、以下の３ファイルが作成されます。
```js:app/javascript/controllers/application.js
import { Application } from "@hotwired/stimulus"

const application = Application.start()

// Configure Stimulus development experience
application.debug = false
window.Stimulus   = application

export { application }
```

```js:app/javascript/controllers/index.js
// This file is auto-generated by ./bin/rails stimulus:manifest:update
// Run that command whenever you add a new controller or create them with
// ./bin/rails generate stimulus controllerName

import { application } from "./application"

import HelloController from "./hello_controller"
application.register("hello", HelloController)
```

```js:app/javascript/controllers/hello_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  connect() {
    this.element.textContent = "Hello World!"
  }
}
```

この3つのファイルにより、hello_controllerが使えるようになります。以下のように属性に`data-controller='hello'`をつけるだけで、 Hello World! と表示されます。
```html
<p data-controller='hello'></p>
```

hello_controllerを使えるようになったのは、`index.js`で以下のようにhello_controllerを登録したからです。
```js
import HelloController from "./hello_controller"
application.register("hello", HelloController)
```
`register`メソッドの第一引数に識別子、第二引数に`hello_controller.js`で定義したcontrollerを与えています。これにより、`data-controller`属性が`'hello'`のHTMLに対して、第二引数で渡したcontrollerが適用されます。

なので、新規作成したcontrollerを使えるようにするには、上記のように`register`メソッドを使えば良いです。例えば、clipboard_controllerを新規作成した場合は、以下のようにcontrollerを登録します。
```js
import ClipboardController from "./clipboard_controller"
application.register("clipboard", ClipboardController)
```

ただ、stimulus controller ジェネレーターを使えば、上記のようなコードを自分で書く必要はありません。
`bin/rails g stimulus clipboard`を実行するだけで、上記のコードを勝手に書いてくれます。

## Import maps

Import mapsを使っている状態で、`bin/rails stimulus:install`を実行すると、上記と同様のファイルが作成されます。ただ、`app/javascript/controllers/index.js`の中身だけが異なります。

```js:app/javascript/controllers/index.js
// Import and register all your controllers from the importmap under controllers/*

import { application } from "controllers/application"

// Eager load all controllers defined in the import map under controllers/**/*_controller
import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading"
eagerLoadControllersFrom("controllers", application)

// Lazy load controllers as they appear in the DOM (remember not to preload controllers in import map!)
// import { lazyLoadControllersFrom } from "@hotwired/stimulus-loading"
// lazyLoadControllersFrom("controllers", application)
```

`eagerLoadControllersFrom`メソッドにより、`app/javascript/controllers`ディレクトリ配下のcontrollerが登録されます。つまり、installタスクで作成されたhello_controllerが使えるようになります。

なので、新規作成したcontrollerを使えるようにするために特段何かする必要はありません。`app/javascript/controllers`ディレクトリ配下に、controllerがあればいいからです。