メドピア開発者ブログスマートフォン用の表示で見るメドピア開発者ブログ集合知により医療を再発明しようと邁進しているヘルステックリーディングカンパニーのエンジニアブログです。TumblrメドピアCTO室フロントエンドエンジニアの小宮山です、よろしくおねがいします。趣味はボルダリングとヨガとピラティスです、よろしくおねがいします。地にて開催されたメドピア開発合宿で取り組んだことについて紹介していきたいと思います。アンパサンドへのウラミツラミタイトルにも挙げたとおり、今回立ち向かったのはSass/SCSSのアンパサンド(&)です。メドピアのリポジトリはほぼSCSSで統一されているので、この記事ではSCSSの記法ベースでコード例を載せていきます。アンパサンド記法は、BEMライクなセレクタを書くときによく利用されるのではと思います。}}アンパサンドを使い、冗長な記述を限りなく減らしたスマートな書き方ですね。書いてるときはDRYなライブ感と共にスタイルを書き進めることができます。この書き方には、セレクタの検索可能性が損なわれるという非常に大きな欠点があります。上述のようなスタイル指定がされたコードに手を入れる場面を想定してみます。変更を加えようとしているファイルはhtmlとjs側です。foo</div>htmlにはheader__fooというclassを持ったタグがあり、jQueryを使ってセレクタからそのタグを取得して何かの操作をしているとします。js側$('.header__foo').hide()何の変哲もない古き良きjQueryコードです。続いてこの処理をVueで置き換えてみます。細かいところは省略しますが、こんな感じになるのではないでしょうか。}})さくっと置き換えることができ、JavaScript側はもうタグに付けておいたclassを必要としなくなりました。不要なものは消せるときに消してしまうのが正義です。header__fooというclassをタグから消してすっきりさせてしまいましょう。foo</div>と迂闊に消してしまう人はさすがにいないと信じたいです。JavaScriptから参照していなくても、CSSからclassを参照している可能性は大いに残っています。このclassに対するCSSを書いた本人なら、このclassがまだ必要であることを覚えているかもしれません。人の記憶は頼りになりませんし、このclassを消していいか迷っているのは何も知らない別人かもしれません。消したいclassがまだどこかで使われているかの判断に迷ったときは、grepするに限ります。どんな結末が待っているかはもう想像がついたかと思います。アンパサンドによる文字列結合で指定されているこのセレクタは、タグに付いているclass名でgrepしても拾われません。}}そして使われていないことを確信し、コード改善と思ってclassを消した開発者には、スタイル崩れという悲劇が待ち受けています。このようにアンパサンドによってセレクタが文字列結合されていると、タグのidやclassがどこで使われているのか見つける手段が大幅に制限されてしまいます。地道に探せば見つけられるかもしれませんが、その労力と、不要なセレクタを減らす地道なコード改善が釣り合うのかは微妙なところです。結局は触らぬ神に祟りなし、必要なのかも分からないidやclassは消えることなく未来に向かって増え続けていきます。purgecss検索妨害と仕組みは同じですが、アンパサンドによるセレクタ結合はpurgecssによる未使用スタイル削除の妨げとなる可能性があります。purgecssは非常に強力なものの、セレクタを使っているかの判定は静的解析によって為されています。どこまで正確に判定しているのかまでは精査できていませんが、不要なリスクを回避する意味でも、アンパサンドやスクリプトを用いた文字列結合によるセレクタ生成は避けたほうが無難です。合宿の地、松本にてgrepを阻害する邪悪なアンパサンドによるセレクタ文字列結合は、すでにメドピアのリポジトリ群に多く入り込んでいました。この現状に立ち向かうべく、アンパサンドを使わない素のセレクタ文字列に変換してしまおうと決意を固めます。メドピアでは年に数回、2泊3日かけて自由なテーマに取り組むことができる開発合宿を開催しています。ボリューム的にちょうど良さそうだったこともあり、アンパサンド変換用のCLIツール開発をテーマに決めて取り組むことにしました。採用言語CLIツールの開発言語にはRustを選びました。フロントエンド関連なのだからJavaScriptやTypeScriptでいいじゃないかという葛藤はもちろんあったものの、舞台はせっかくの開発合宿です。今の最善でないとしても、興味のある技術にフォーカスしてこそ開発合宿です。普段とは違う言語に四苦八苦したくなるときだってあるんです。成果物リポジトリはこちら。github.comCLIまずは当初目的通りCLIツールです。clapというCLIツール作成用便利パッケージを使うと引数解析やヘルプ表示などを簡単に作れます。pathファイルを書き換えたりといったCLI特有の機能以外はWebAssembly版と同じ動作なので、デモなどはそちらに引き継ぎます。WebAssemblyフロントエンド、Rustというキーワードが来たら当然続くのはWebAssemblyでしょう。冒頭で長々と書いた当初の目的を果たすにはCLIツールさえあれば十分ですが、舞台は開発合宿です。隙あらば気になる技術に全力投球していきます。成果物netlifyにデモサイトを用意したのでお試しください。いうのも正直なところ今回の成果物・・・作った本人から見ても実用レベルには至りませんでした、無念。「アンパサンドを置換するだけだし実装なんて簡単だろう」と気楽に作り始めてしまったのが運の尽き、Sassアンパサンド(というよりSassそのもの)は想像以上に手強い相手でした。この変換例を御覧ください。変換例みにくい!!!そうなんです。アンパサンドを解決するにはセレクタのネスト構造を解決する必要があり、そのために記述が複雑になることを避けられませんでした。ちなみに余談ですが、当初は勢いで走りすぎてこういう変換をしていました。間違い探しとしてお収めください。間違い探し制約100歩譲ってみにくさは我慢するとしても(diffが死ぬので譲りにくいですが)、仕様的に無視しにくい大きな制約もいくつか残ってしまいました。厳しいのは複数行のセレクタに対応できていないことです。見るも無残な姿になってしまいました。「1行ごとに処理すればいいだろう」という謎の自信に満ちた実装方針により、複数行セレクタへの対応が必要と気付いたときには既に軌道修正が間に合いませんでした。あと地味にSassを諦めてSCSS専用になっています。CLIとWebAssembly両対応ビルド気を取り直して、今回一番苦戦した点の紹介です。実は実装を差し置いて、CLIとWebAssemblyの両方にRustコードをビルドすることにかなり苦戦しました。RustやCargo.toml自体への理解度もあまり深くなく、試行錯誤の末になんとか形になった方法をここで紹介したいと思います。シンプルなWebAssemblyビルドRustをWebAssembly化し、ウェブページとして公開する1連の流れ自体はこちらの記事を大いに参考とさせていただきました。webbibouroku.combindgen、wasm-pack、create-wasm-appなど、便利なツールの導くままにWebAssemblyなウェブページを作ることができてしまいます。RustをWebAssemblyにビルドするだけなら解説通りにwasm-packを使うだけです。今回はもう1つのターゲット(こちらが本命のはずなんですが)としてbinaryにもビルドする必要があります。異なる依存パッケージCLIツールとしてはディレクトリ内のファイルを一気に処理させたかったので、dependenciesにwalkdirというファイル探索用パッケージを追加していました。buildコマンドを実行すると以下のようなエラーを吐かれてしまいます。`imp`原因は推測ですが、WebAssemblyにビルドできない何か(walkdirなのでおそらくファイル操作系)が混ざっていると判定されているのだと思います。その証拠に、Cargo.tomlのdependenciesからwalkdirをコメントアウトすると無事にビルドが成功します。WebAssemblyにビルドするときだけ手動でその行をコメントアウトすれば解決します!!!許されません、これは許されません。ビルドコマンドをただ実行するだけなのに、こんなにも露骨な運用でカバープロセスを挟み込むなんて許されるわけがありません。README.mdにこんなビルド方法の解説を書くこともとてもできません。本体のコーディング以上に血眼になって探し、ついにここで答えを見つけました。修正後のCargo.tomlの書き方はこちらです。bin)だけビルド時の依存関係に含めてくれるようになります。大まかな流れは上図のようになっています。buildから除外することに成功しました。binを引数に加えることで依存パッケージをしっかりと認識してくれます。引数追加程度ならREADME.mdに書くこともきっと許されることでしょう。本当はCLIとしてビルドするときにWebAssemblyでしか使わないパッケージも除外したかったのですが、こちらはwasm-packをさらに解析する必要がありそうで今回は泣く泣く断念しました。こちらの問題にも対応した完全版両対応ビルド設定の模索は今後の課題です。成果物やデモを公開するには、やはりウェブブラウザで見れるというお手軽さは魅力的です。本命のCLIツールを作り込みつつ、さくっと触れるデモをウェブで公開したいという贅沢な欲求をWebAssemblyは見事に叶えてくれました。まとめSass/SCSSの邪悪なアンパサンドへのウラミツラミからスタートし、それっぽく動くけど妥協点満載な解決ツールを作り、WebAssemblyの知見を紹介して締めるという全くまとまりのない記事となってしまいましたが、メドピア開発合宿3日間が見事に集約されています。自分で言うのもあれですが見事に集約されています。実は人生初の開発合宿というイベントでした。好きなテーマに取り組んでいいという我らがCTO福村の言葉をそのまま受け取り、このように本当に好きなことに取り組むことができた濃密な3日間となりました。これで当初目的だったアンパサンド撲滅も達成できていたら最高だったのですが、残念ながら力及ばず。なんと、同じく合宿に参加していたフロントエンドエンジニア村上(@pipopotamasu)がstylelint-scssのruleでセレクタのアンパサンド結合を禁止するというスマートすぎるPRをさくっと作って本家のルールに加えてくれました。github.com邪悪なアンパサンド勢力の拡大はこうして食い止められたのです。松本の地にて立ち上がっていたのは村上です。僕は何もしていません。持つべきものは仲間です。メドピアではフロントエンドエンジニアの仲間を絶賛募集中です。՞)☝︎是非読者になってくださいメドピアでは一緒に働く仲間を募集しています。SREの侘美(たくみ)です。普段はRai...2019-07-04開発合宿に行ってきました!@松本メドピアのサーバーサイドサウナーの川井田です。メドピアでは...2019-05-13Ruby2.7の(実験的)新機能「パターンマッチ」で遊ぶはじめまして、メドピアのサーバサイドエンジニアの草分です。RubyKaigi2018に参加...2018-04-25ActiveModelSerializersを使った所感こんにちは。メドピアエンジニアの保立です。月別アーカイブリンク医師専用サイト「MedPeer」エンジニア採用はこちら!スターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。