見出し画像

Vite+Dart Sass+Vanilla JSな開発環境について

BLUE B NOSEでは、WordPressテーマに用いるCSSやJS、次世代フォーマットの画像を生成するために、Viteを中核としたVanilla JS、Dart Sass向けのボイラープレートを用いています。今回は、なぜViteを用いているのか、なぜSassを用いるのかといった点も含め、開発環境についてざっくりお伝えします。

オウンドメディアの方では、BLUE B NOSE(以下:BBN)で使用しているWordPressテーマについてザックリと解説したので、こちらではそこで用いるCSSやJS、画像を生成するための開発環境、ボイラープレートについても簡単に触れてみましょう。最新、最先端とは言い難い知見ですが、何かのお役に立てば幸いです。


詳細は、リポジトリへ

BBNのサンプル事例ページからもリンクさせていますが、例えば「BX-00」で用いているCSSやJSを生成するための開発環境は、こちら(https://github.com/Yuuji-Hasegawa/html-bx-00)で公開しています。
リポジトリを眺めて何となく分かる方には、これ以上の解説は不要でしょう。

強いて言えば、`npm-scripts`ディレクトリや、package.jsonの"image"や"icon"のスクリプトぐらいでしょうか。これは、`src/images`内の画像を`src/public/img`へコピーしつつ、imageminで最適化をかけつつ、sharpで、PWA用のiconをサイズ別にリサイズしたり、WebPやAvif画像を生成するためのものになります。画像生成、最適化用のキャッシュは特に設けていないので、ビルド時間が問題になる場合はテコ入れ必須ですね。

後は、Viteの環境にお任せしつつ、Dart SassやらES ModulesなVanilla JSを使うためのアレコレ、各種linter等が追加されている程度です。

Pug等のテンプレートエンジンやReact周りのHTML用のアレコレは特に導入せず、Emmetで補完すれば十分というか、余り色々足さない方が使い回しやすいのではという判断で、HTMLはほぼ素のままにしています。

Vite+Pnpmな環境で、HMR(ホットリロード)が有効な開発用サーバの立ち上げも、`dist`ディレクトリへファイルを書き出すビルドの実行も、それなりに遅くない環境なのではと思っています。

Sass(とBabel)のために導入し始めたタスクランナー

徐々にCSSでもできることが増えてきて、技術的負債の側面もありそうなDart SassをBBNでは今も取り入れています。ES ModulesなVanilla JSをHMRの環境で構築するためにも、gulp等のタスクランナーは重要ですよね。筆者もそうでした。

ただ、libSassからDart Sassへ移り変わる頃というか、本格的にES Modulesへ対応しなければならない時期に、gulp v4で相応の環境、正しいと思われる環境を構築したり、gulp + webpackな体制を作ってみたり、webpack単体で完結するボイラープレート等にも挑戦してみましたが、gulpのみやgulp+webpack併用の場合は、gulpfileが秘伝のタレになり過ぎたり、Nodeの新しいバージョンに対応していないものが増えてきたり、webpack単体だと動作がどんどん重くなったり、js以外のバンドルが思った動きじゃなかったりと、色々気になることも増えてきました。

その後、一度Rollupを導入した環境というのも触ってはいましたが、Viteに触れてみたら、諸々の環境構築が非常に楽で、Dart Sass向けの準備もそこまで大変ではなく、Vanilla JSで構築していく上でも、そこまで必死に学び直さなくても使えそうというところで、Viteで行こうと決めました。

Pnpmも、npmよりYarnが早いみたいなところで一時そちらをメインで触っていましたが、Pnpmの方が早いというか、動作も癖がなくて使いやすかったので、結果的にこちらを選択しています。

結果的に、gulpfileの中で処理していたものが外にファイルが分散する形で環境構築をしていたりするし、imageminやsharpなど画像処理に関してはViteの一連の処理からは外して、npm-scriptを独自に組んで解決したりと少々トリッキーなことをしている部分もある今の開発環境ですが、Viteとrenovateによってそれなりに安定して動作しているので、これはこれで良いのではという体感です。

CSSの基本設計は、『EVERY LAYOUT』+ユーティリティ

過去に何度か言及していますが、『EVERY LAYOUT』を参考にした構造物 + 個別のコンポーネントに、ユーティリティ、ヘルパーを付与する方向で、CSSを設計しています。

`src/styles/generic/_resets.scss`でハード目のリセット、

*:where(:not(iframe, canvas, img, svg, video, svg *)) {
  all: unset;
  display: revert;
}

を実行しつつ、`src/styles/objects/`で『EVERY LAYOUT』由来の構造物(接頭語は`o-`)、`src/styles/components/`で個別のコンポーネント(接頭語は`c-`)、`src/styles/utility/`で接頭語を`u-`としたユーティリティ、ヘルパーを記述するようにしています。

Dart Sassを用いるので、それぞれのディレクトリ内に`_index.scss`を設定し、そこから`@forward`で必要なファイルを読み込み、別の場所ではディレクトリ指定で`@use "../hoge" as hoge;`のように使えるようにしています。

後は適宜BEM風に、`__`で子要素、`--`でModifierを設定する形を取っています。

なお、WordPressで用いる観点から、ブログ記事の本文部分に当たる`the_content()`を囲む要素(仮に`.c-entry`とする)の中を除き、基本的にセレクターにスタイリングすることを避け、classを付与するか、擬似クラス、その他の属性を用いてスタイルを割り当てるようにしています。(タグの意味と見た目の切り離しも同時に実施)

これは、CSSのレンダリングやパフォーマンスを考慮した時、「右側」から解釈されるから、です。
記述する時の感覚としては、「親要素の中のセレクター」のように書きますが、実際は「セレクターから親要素」を解釈しにいくので、セレクター任せのCSSを書くよりは一々classを割り振って書いた方が良いのでは、という判断からです。結局、入れ子にしていたり、特定のclass下の場合などを割り振っていたりもするので、適当と言えば適当なんですが......。

`the_content()`中身の場合は一々割り当てるのも流石に面倒だろうし、ということで

.c-entry p{

}

みたいなのもありかなという判断です。

また、今のところユーティリティ、ヘルパークラスではそこまで「カスタムプロパティを用いた外部からの変更」は実施していません(というか、全体的なメンテナンス、統一等がまだ間に合っていません)が、今後はそちらの比重を移した作り方もありなのかなぁ、という気もしています。

Sassの恩恵も、カスタムプロパティの恩恵も受けたい

CSS単体でもネストができるようになったし、カスタムプロパティという変数も使えるし、Scoped CSSやCSS Modules、CSS in JSやら、Tailwind CSやら、無理にSassを使わなくても良さそうな時代だし、もはやSassは技術的負債だ、と切り捨てるのも悪いとは思いませんが、BBNではカスタムプロパティ等のPost CSSの恩恵も、Sassの恩恵も両方受けたいので今もSass、Dart Sassも導入しています。

Sassを使わずに、CSSのフレームワークだけで柔軟な運用というのも利点があるとは思いますが、Sassの変数や関数が得意なことと、カスタムプロパティの得意なことやCSS関数の利点も踏まえた上で、併用する利点もあると考えています。

CSS単体の運用の場合、確かにコンパイルする環境やHMRの開発環境も不要で書きやすいですが、その分破綻もしやすい側面があります。ファイルを分割して管理しやすくした場合も、その後の読み込みや統合のパフォーマンスが課題になります。

Sassの場合、導入コストや学習コスト、あるいはコンパイルの環境に振り回されることもありますが、導入しにくい分、破綻しにくく堅牢な設計のCSSを書きやすくなります。ファイルを分割したり、CSSに現れない部分がどれだけ肥大化しても、生成結果のCSSが線形で拡大するとも限りません。

Sassの方が計算に強く、CSSの方が動的な変化に強いので、どの場面でどっちを用いるべきかを考えながら、CSSに残したくない部分、プロジェクトを通して統一したい部分はSassの変数やmapを活用するというのが良いような気はします。

例えば、

@media (prefers-color-scheme: dark) {

}

とメディアクエリを用いてカラーを変更する場合はカスタムプロパティの方が向いていますが、

background: rgba(map.get(setting.$sys-light, scrim), 0.5)

とHEXで保有しているカラーから、rgbaを出力させるにはSassの方が向いています。CSSとしてコンパイルされた後はカスタムプロパティ、そうなる前の時点の計算はSassに利点があると言えます。

こうやって工夫して記述しても、最終的にはプロパティ別にCSSを生成するような形がベター、無難という結論へ帰結するのもよく分かりますが、堅牢さと柔軟さを併せ持ちつつ、出力した後のCSSの使いやすさを考慮すると、Sassもカスタムプロパティ(= Post CSS的な恩恵)の併用が良い、まだしばらくはSassも使っていくというのが現段階の結論です。

Vanilla JSはViteのお作法で

Javascriptに関しては、一旦jQuery等は入れない方向にしつつ、その上でViteのお作法に則ったやり方を選択しています。(例えば、`src/index.html`で

<script type="module" src="scripts/main.mjs"></script>

を呼び出す、など)

`.mjs`の拡張子で呼び出すのは、mainのみにして、後は適宜ファイルを分けて`.js`拡張子としたものを`main.mjs`で呼び出す形にしています。

メニューのオンオフの挙動や、iframeで呼び出すGoogle Mapsの埋め込みやYoutubeの埋め込みに対するLazy loadをIntersectionObserver

を使った手法で構築したり。

Swiperを使ったスライドショーや、Lightbox関連のモジュールも、`main.mjs`で設定する形を想定し、それ以外のお手製関数は各ファイルの中で、

export const 関数名 = () => {

}

とすることで、それっぽい記述となるよう心がけてはいますが、より良いやり方はあると思うので識者の皆さんにお知恵をお借りできればというところです。

あくまでも、BBN向けのオレオレボイラープレート

「デザインセンスがなくても、それなりのものを作れる」を一時的なコンセプトに、色もベースの一色さえ決めてしまえば機械的にダークモードの配色、カラーマネジメントもできる環境を作っています。
カスタムプロパティを含めたユーティリティな組み方はまだまだ整備不完全ですが、その辺りも徐々にブラッシュアップできていけば、プロジェクトを跨いで再生産性が高そうなフレームワーク、オリジナルのBootStrap、デザインシステムの構築にも至れるのではと考えています。

ただ、あくまでも我々のサービスで導入するのに丁度良い、レスポンシブでも崩れにくい、情報量の少なさを補うフロントエンドといったパフォーマンス重視のボイラープレートでもあるので、高機能とは言い難い環境でもあります。

それでも一回導入して、ちょっと慣らし運転をしてしまえばそれなりに使い回せるとも思うので、ちょっと気になるという方は、是非お試しくださいませ。

もっともっと、気楽に組みたい

BBNでは、プロジェクトを超えて活用可能なデザインシステム、共通規格みたいなものができないかと考えています。Twitter Bootstrapでは過度だし、他のフレームワークでは細か過ぎるし、組みやすさという観点からも、高速表示のパフォーマンスという観点でも、ほぼベストと呼べそうなパターンを集約した形、建売のデザイナーズ物件のような短納期、量産向けのローコードなボイラープレートを目指しています。

可能ならどんどん使っていただいて、自分たちだけでは足りない知見、思い付かない効率化も含めてご意見いただきながら、もっともっと使いやすい開発環境、ボイラープレート、共通規格といったものを固めていければと考えていますが、人の手も介入させながら楽に作れる環境作りに、一緒に取り組んでみませんか?

今後も「お役立ち情報」をお届けします

BLUE B NOSEでは今後も、経験を通じて得たナレッジの共有や、独自視点でのお役立ち情報をお届けします。HP上でもコンテンツを発信する予定なので、もしよろしければ当アカウントのフォローや、HPのチェックもお願いします。


この記事が気に入ったらサポートをしてみませんか?