Lightning CSSをViteに導入する
最近Lightning CSSというものを知ったので、ViteのプロジェクトにLightning CSSを導入する方法を紹介したいと思います。
Lightning CSSとは
Lightning CSSとは一体どういったものなのでしょうか。
An extremely fast CSS parser, transformer, bundler, and minifier.
簡単にいうと、CSSのParser / Transformer / Bundler / Minifierの役割を担うツールです。
Rust製のツールであり、そのビルド速度はESBuilをも凌ぐ速度となっています。
Lightning CSS lets you use modern CSS features and future syntax today.
と書かれているようにLightning CSSを導入することで、最新のCSSの機能と将来の構文を使うことが可能となります。
実際にどうような構文がサポートされているのかはGitHubに記載がありますので、そちらをご参照ください。現時点(2022.12.5)での一例を挙げるとCSS Nesting
やCustom Media Queries
が使えるようになります。
とりあえず機能だけでも試してみたいという方は公式のPlaygroundが用意されているので、ぜひそちらで試してみてください。
ドキュメントを読む限りだと、もともとParcel向けに開発されている印象を受けますが、ParcelでなくてもJavaScriptやCLIなどから使うことができます。本記事ではViteの自作プラグインとしてプロジェクトに組み込む方法を紹介します。
Lightning CSSをViteに導入する
本記事ではViteの自作プラグインとして、Lightning CSSをViteプロジェクトに導入したいと思います。
プロジェクトの作成
まずはyarn create vite
でViteプロジェクトの作成を行いましょう。
本記事ではyarn
を使います。未検証ですがnpm
でも問題はないと思います。
プロジェクトの作成については基本的に上記の手順にしたがいます。
$ yarn create vite
//...略
✔ Project name: … vite-lightningcss
✔ Select a framework: › Vanilla
✔ Select a variant: › TypeScript
プロジェクト名はvite-lightningcss
(ここは任意のプロジェクト名にしてください)、frameworkはVanilla
、variantはTypeScript
を選択しました。
$ cd vite-lightningcss
$ yarn
プロジェクトルートに移動し、yarn
コマンドでパッケージをインストールします。
$ yarn dev
その後yarn dev
コマンドでローカルサーバーが立ち上がれば、プロジェクトの作成は完了です。
不必要な記述の削除とファイルの整理
この状態では以下のようなフォルダ構成になっていると思います。
.
├── index.html
├── node_modules
│ └── ...略...
├── package.json
├── public
│ └── vite.svg
├── src
│ ├── counter.ts
│ ├── main.ts
│ ├── style.css
│ ├── typescript.svg
│ └── vite-env.d.ts
├── tsconfig.json
└── yarn.lock
本記事において、不必要なフォルダ・ファイルの削除と記述の整理を行います。
public
ディレクトリ、src
以下にあるcounter.ts
とtypescript.svg
は必要ないので削除します。
$ rm -r public src/counter.ts src/typescript.svg
次にsrc/main.ts
とsrc/style.css
を書き換え、最低限の記述だけを行います。
import './style.css';
* {
margin: 0;
padding: 0;
}
最後にsrc/index.html
も書き換えておきます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Lightning CSS</title>
</head>
<body>
<h1 class="title">Vite + Lightning CSSのサンプル</h1>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
ここまでの作業で以下のようなフォルダ構成になりました。
.
├── index.html
├── node_modules
│ └── ...略...
├── package.json
├── src
│ ├── main.ts
│ ├── style.css
│ └── vite-env.d.ts
├── tsconfig.json
└── yarn.lock
プラグインを作成する
前準備がおわったところで、プラグインの作成を行なっていきましょう。
詳細は上記にあるので、適宜ご参照してください。
まず必要なモジュールを前もってインストールしておきます。
$ yarn add -D lightningcss browserslist @types/node
lightningcss
だけでなく、browserslist
もインストールしていますが、これはターゲットのブラウザ指定を簡易にするためです。lightningcss
単体でもターゲットブラウザの指定は可能ですが、少し煩雑になるため、browserslist
を使用します。
次にプロジェクトのルートにvite.config.ts
を作成し、以下のように記述します。
$ touch vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [],
});
次にプラグインの処理を記述するplugins/vite-plugin-lightningcss.ts
を作成します。
$ mkdir plugins
$ touch plugins/vite-plugin-lightningcss.ts
ViteプラグインAPIではrollup.jsと同様にいくつかのビルドフックが提供されています。
今回はLightning CSSを用いてCSSを変換するわけですが、このような処理ではtransform
フックを使用できます。
Lightning CSSの使い方については以下に記載があります。
上記を踏まえて、プラグインには次のように処理を記述します。
import browserslist from 'browserslist';
import {
transform as CSSTransform,
browserslistToTargets as CSSBrowserslistToTargets,
} from 'lightningcss';
import { type Plugin } from 'vite';
const cssRegex = /\.(css)$/;
// browserslistでtargetsを指定
const browserTargets = CSSBrowserslistToTargets(browserslist('>= 0.25%'));
const vitePluginLightningcss = (): Plugin => {
return {
// vite-plugin-*で名前をつける
name: 'vite-plugin-lightningcss',
// transformフックでCSSの変換処理
transform(src, id) {
// CSSファイルの処理
if (cssRegex.test(id)) {
// https://github.com/parcel-bundler/lightningcss/blob/master/node/index.d.ts
// オプションについては上記参照
const { code, map } = CSSTransform({
filename: id,
code: Buffer.from(src),
targets: browserTargets,
// デフォルトではnestingとcustomMediaがfalseなのでtrueにする
drafts: {
nesting: true,
customMedia: true,
},
});
return {
code: code.toString(),
map: map?.toString(),
};
}
// CSSファイル以外は何も処理せず返す
return {
code: src,
};
},
};
};
export default vitePluginLightningcss;
本記事ではCSS Nesting
とCustom Media Queries
をtrue
にしていますので、ご注意ください。
プラグインの記述は完了です。作成したプラグインをvite.config.ts
から読み込みます。
import { defineConfig } from 'vite';
import vitePluginLightningcss from './plugins/vite-plugin-lightningcss';
export default defineConfig({
// 作成したプラグインを読み込む
plugins: [vitePluginLightningcss()],
});
スタイルの反映
ここまできたらyarn dev
でローカルサーバーをたちあげてみましょう。
<!-- ...略... -->
<body>
<h1 class="title">Vite + Lightning CSSのサンプル</h1>
<script type="module" src="/src/main.ts"></script>
</body>
<!-- ...略... -->
現状HTMLファイルには上記の記述があるので、「Vite + Lightning CSSのサンプル」の文字が表示されていれば問題ありません。
では実際に将来のCSS構文が使えるのか試してみます。
@custom-media --narrow-window (max-width: 600px);
* {
margin: 0;
padding: 0;
}
/* CSS Nesting Module */
/* https://www.w3.org/TR/css-nesting-1/ */
body {
color: red;
.title {
color: green;
}
}
/* Custom Media Queries */
/* https://www.w3.org/TR/mediaqueries-5/#custom-mq */
@media (--narrow-window) {
body {
.title {
color: blue;
}
}
}
上記はCSS Nesting
とCustom Media Queries
を導入した記述になります。上記のスタイルを適用した場合、次のように表示されます。
ビューポート幅590pxのとき、文字色はblue
となる。
ビューポート幅610pxのとき、文字色はgreen
となる。
画像をみてもわかるように、CSS Nesting
とCustom Media Queries
が反映されていますね。
この状態で、一度yarn build
コマンドでビルドしてみましょう。
dist/assets
以下に任意のCSSファイルが生成されると思います。その中身を確認してみるとCSSが以下のように変換されていることがわかります。
* {
margin: 0;
padding: 0;
}
body {
color: red;
}
body .title {
color: green;
}
@media (max-width: 600px) {
body .title {
color: #00f;
}
}
以上で、Lightning CSSをViteに導入することができました。
サンプルコード
本記事で行った作業結果を以下のリポジトリに置いてあります。全体のコードを確認したい方は以下をご参照ください。
おわりに
Lightning CSSはParcel以外でも簡単に使うことができます。
最新、もしくは将来のCSSの機能や構文をお手軽に試すことが可能なので、興味のある方はぜひ使ってみてください。
参考
Discussion