🥵
rubyLspをモノレポで動かす
問題
以下のようなモノレポの構成でrubyLspを動かしたい
my_project
├── backend
└── frontend
このとき.vscode/settings.json
は以下のようになっているが、rubyLspによるフォーマットや補完などが効いている様子がない。
.vscode/setting.json
{
"rubyLsp.formatter": "rubocop",
"rubyLsp.rubyVersionManager": {
"identifier": "rbenv"
},
"[ruby]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "Shopify.ruby-lsp"
}
}
原因
workspaceごとにrubyやgemのバージョンが異なったりするかもしれないため、rubyLspはworkspaceごとに単一のlanguage serverを立てる。
rubyLspは各WorkspaceのルートにあるGemfileを参照していると思われるが、モノレポだとGemfileはルートにはないので動かなかった(のだと思っている)
解決方法
以下のどちらかで解決できそうだった。
- vscodeのmulti-root workspace機能を使う
- devcontainer内で作業する
vscodeのmulti-root workspace機能を使う
vscodeにはmulti-root workspaceという機能があり、(任意の名前).code-workspace
といったファイルを用意することで以下のようなことが実現できる。
- モノレポ内の1つ1つのフォルダをrootフォルダー的な扱いをする
- workspace全体で共通の設定を記述できる
- 各rootフォルダー内で更に
.vscode/settings.json
を作ることで、共通の設定を上書きできる
rubyLspを動かすには.code-workspace
には以下のような内容を記述すればいい
.code-workspace
{
"folders": [
{
"name": "my_project",
"path": "."
},
{
"name": "frontend",
"path": "./frontend"
},
{
"name": "backend",
"path": "./backend"
}
],
"settings": {
// name: my_project には通常そのサブディレクトリであるfrontend、backendディレクトリも表示されてしまう
// これらはそれぞれ個別に表示しているものと重複してしまうので、name: my_projectの方には表示しないようにする
"files.exclude": {
"frontend": true,
"backend": true
},
"rubyLsp.formatter": "rubocop",
"rubyLsp.rubyVersionManager": {
"identifier": "rbenv"
},
"[ruby]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "Shopify.ruby-lsp"
}
}
}
devcontainer内で作業する
基本的には以下とかを参考にすればいいが、vscodeのgitの機能を使うためにルートを含めたりしなかったり、ビルドを毎回しないようにするための設定をする必要がある。
以下のようにdevcontainer用のcompose.yamlを別で用意する。
compose.devcontainer.yaml
services:
frontend:
volumes:
- .:/workspace:cached # .gitなどもdevcontainer内に含める
backend:
volumes:
- .:/workspace:cached
さらに以下のようにdevcontainer.json
を記載する
devcontainer.json
{
...
"dockerComposeFile": [
// compose.yamlをcompose.devcontainer.yamlで上書きする
// これはdocker-compseの -f オプションで複数指定したときの挙動に相当する
"../../compose.yaml",
"../../compose.devcontainer.yaml"
],
"shutdownAction": "none" // devcontainer間でswitchするときにcontainerを停止しない
"customizations": {
"vscode": {
"extensions": [
"Shopify.ruby-lsp",
],
"settings": {
"rubyLsp.formatter": "rubocop",
"rubyLsp.rubyVersionManager": {
"identifier": "rbenv"
},
"[ruby]": {
"editor.defaultFormatter": "Shopify.ruby-lsp",
"editor.formatOnSave": true
},
}
}
},
...
}
最後に
ゴリ押し感があるので、なんかいい方法がある気がしている
Discussion