blog.bouzuya.net

2019-01-28 続 PureScript のプロジェクトで PostCSS (で CSS Modules) を使う

PureScript のプロジェクトに PostCSS で CSS Modules を適用してみた話 (2019-01-26) の続き。

前回の流れと問題の解決

前回の流れと残った問題・その解決について書く。

bouzuya/purescript-react-basic-repository-list に CSS Modules を適用しようとした。方法としては postcss-cli から postcss (postcss-modules プラグイン) を使っている。 postcss-cli を使う理由は webpack による import / require 依存の方法は PureScript では扱いにくいからだ。

これでうまくいくと思ったのだけど問題が起きた。 parcel が postcss-cli 用の postcss.config.js を解釈して不要な変換をしてしまった。 parcel 側の設定方法は見当たらなかった。

最終的にこの問題の解決策としては postcss.config.js を別ディレクトリに移動し postcss-cli の --config でディレクトリを指定する方法を選択した。これでファイルの変換は問題がなくなった。

利用時の流れ

ここまででの利用時の流れを整理するとこうだ。

  1. postcss-cli により src/**/*.cssdist/style/**/*.csssrc/**/*Style.purs へ変換される
  2. cat dist/style/**/*.css > index.css により index.css をまとめる
  3. index.htmllink 要素で index.css を参照する
  4. src/**/*.purssrc/**/*Style.purs が export した scopedName を参照する (例: button { className: Style.button })
  5. dist/ src/**/*Style.purs index.css.gitignore により git の対象から外す

だいたい CSS Modules を素朴に使える状態のはず……。

output/ に反映されない問題

ところがまた別の問題が起きた。生成された *Style.purs からの定数値を VS Code で補完できない問題だ。

ここで言う補完とは VS Code の拡張である PureScript IDE の機能のひとつだ。 PureScript IDE は保存した *.purs を自動でビルドし output/ (既定値) に JavaScript を出力する。 output/ にある状態 (PureScript IDE によるコンパイルができている状態だと思う) なら補完が効くのだろう。

調べてみたところ *Style.purs は生成されているもののコンパイルされておらず output/ の JavaScript には反映されていなかった。 *Style.purs を開いて変更し保存すれば output/ に反映される。しかし自動生成されたファイルをわざわざ開いて保存する手順など許容できない。

補完だけならまだ無視できそうだが、 output/ に反映されないので parcel index.html の結果にも反映されない。つまり編集した CSS がブラウザに反映されない。こうなるとさすがに無視できない。

PureScript IDE のソースコードを読むことにした。

PureScript IDE と原因の予想

↑に書いたとおり PureScript IDE (nwolverson/vscode-ide-purescript) は VS Code 拡張のひとつである。

VS Code の言語のための拡張なので LSP: Language Server Protocol に対応した Language Server を利用している。 PureScript の Language Server である npm:purescript-language-server (nwolverson/purescript-language-server) だ。

この拡張が提供するコマンドは拡張自体によるものと Language Server によるものの二種類がある。ただ今回の事象にコマンドは関係ないので掘り下げない。

調査前の予想は↓だった。

  • Language Client がファイルの変更を監視・送信できていない
  • Language Server がファイルの変更を処理できていない

調査

PureScript IDE は Language Server を npm:vscode-languageclient (Microsoft/vscode-languageserver-node) の LanguageClient 経由で使っている。これは VS Code の Language Server Extension Guide からして、おそらく VS Code の拡張 (Node.js 環境) では一般的な方法だと思う。ざっと見た感じおかしな点はなさそうだった。

Language Server (nwolverson/purescript-language-server) 側のログを見てみることにした。デバッグ方法がよく分からないので ~/.vscode/extensions/nwolverson.ide-purescript-0.20.7/node_modules/purescript-language-server/server.js を置き換えて適当にログを入れてみることにした。

git clone https://github.com/nwolverson/purescript-language-server
cd purescript-language-server/
npm install -g purescript pulp
# 編集
npm run build
cp server.js ~/.vscode/extensions/nwolverson.ide-purescript-0.20.7/node_modules/purescript-language-server/server.js

実際には purescript と pulp は devDependencies に入れた。雰囲気は↑のような形で。

調査結果

結果としては予想の後者側。 Language Server がファイルの変更を処理できていなかった。

onDidSaveDocument 。 つまり VS Code での保存時にはビルドされる。

https://github.com/nwolverson/purescript-language-server/blob/ad8315d66f1c7ac5f422d868ed7ea3e776cd62d3/src/LanguageServer/IdePurescript/Main.purs#L210-L227

onDidChangeWatchedFiles 。つまり (VS Code を使用しない) ファイルの作成・削除・変更時にはビルドされない。

https://github.com/nwolverson/purescript-language-server/blob/ad8315d66f1c7ac5f422d868ed7ea3e776cd62d3/src/LanguageServer/IdePurescript/Main.purs#L200-L205

VS Code のコマンド View: Toggle Output から OUTPUT を表示してセレクトボックスから IDE PureScript を表示すると "IDE PureScript" という名前の OutputChannel の内容が表示される。これが PureScript IDE の使用している OutputChannel だ。そこに↑のログも表示される。

↓で試しにファイルの作成・変更時にビルドされるような形にしてみた。

https://github.com/bouzuya/purescript-language-server/tree/build-on-changed https://github.com/bouzuya/purescript-language-server/commit/945b1e0d5b22d980d79d1737c0d41b9628f98d34

良い感じだ。

たぶん一通りの問題が解決した。↑の変更で Pull Request して良いのかはよく分からない。なぜ onDidSaveDocument でしかビルドしないのかが分かるほど詳しくないからだ。また nwolverson/purescript-language-server は Atom の拡張からも使われていそうなのでなおのことだ。

PureScript IDE や PureScript の Language Server についての知識がすこし増えた。