sass(Dart Sass)の使い方 — JavaScript製Sassコンパイラ完全ガイド
一言でいうと
sass は、Dart Sassを純粋なJavaScriptにコンパイルした Sass/SCSS のコンパイラパッケージです。ネイティブバイナリや外部依存なしで、Node.js 上で SCSS/Sass を CSS に変換できます。
どんな時に使う?
- Webアプリケーションのビルドパイプラインで、SCSS ファイルを CSS にコンパイルしたいとき
- Webpack・Vite などのバンドラーと組み合わせて、スタイルシートのプリプロセスを行いたいとき
- Node.js スクリプトやCLIツールから、プログラム的に Sass のコンパイルを実行したいとき
インストール
# npm
npm install --save-dev sass
# yarn
yarn add --dev sass
# pnpm
pnpm add -D sass
# グローバルインストール(CLIとして使う場合)
npm install -g sass
基本的な使い方
ファイルからコンパイル
import * as sass from 'sass';
// ファイルを指定してコンパイル(同期版・推奨)
const result = sass.compile('src/styles/main.scss');
console.log(result.css); // コンパイル済みCSS文字列
// 非同期版(同期版より大幅に遅いため、必要な場合のみ使用)
const asyncResult = await sass.compileAsync('src/styles/main.scss');
console.log(asyncResult.css);
文字列からコンパイル
import * as sass from 'sass';
const result = sass.compileString(`
$primary: #3498db;
.container {
color: $primary;
&__title {
font-size: 2rem;
font-weight: bold;
}
}
`);
console.log(result.css);
// .container { color: #3498db; }
// .container__title { font-size: 2rem; font-weight: bold; }
CLI での使い方
# 単一ファイルのコンパイル
sass src/styles/main.scss dist/styles/main.css
# ウォッチモード
sass --watch src/styles:dist/styles
# 圧縮出力
sass --style=compressed src/styles/main.scss dist/styles/main.css
よく使うAPI
1. compile() — ファイルパスからコンパイル
最も基本的かつ推奨される API です。同期的にファイルをコンパイルします。
import * as sass from 'sass';
const result = sass.compile('src/styles/main.scss', {
style: 'compressed', // 'expanded'(デフォルト)または 'compressed'
sourceMap: true, // ソースマップを生成
loadPaths: ['node_modules'] // @use / @import の探索パス
});
console.log(result.css); // コンパイル済みCSS
console.log(result.sourceMap); // ソースマップオブジェクト(sourceMap: true の場合)
2. compileString() — 文字列からコンパイル
SCSS/Sass の文字列を直接コンパイルします。動的にスタイルを生成する場合に便利です。
import * as sass from 'sass';
const result = sass.compileString(
`
@use 'variables' as vars;
body {
background: vars.$bg-color;
}
`,
{
// 文字列コンパイル時の @use / @import 解決のベースURL
url: new URL('file:///path/to/project/src/styles/entry.scss'),
// Indented Syntax(.sass)として解釈する場合
syntax: 'scss', // 'scss' | 'indented' | 'css'
loadPaths: ['src/styles'],
}
);
console.log(result.css);
3. compileAsync() / compileStringAsync() — 非同期コンパイル
非同期のカスタムインポーターやカスタム関数を使う必要がある場合に使用します。
import * as sass from 'sass';
// 非同期版(注意:同期版より大幅に遅い)
const result = await sass.compileAsync('src/styles/main.scss', {
style: 'expanded',
sourceMap: true,
});
const stringResult = await sass.compileStringAsync(
'$color: red; .test { color: $color; }',
{ style: 'compressed' }
);
console.log(stringResult.css); // .test{color:red}
パフォーマンス注意: 公式ドキュメントでも明記されているとおり、
compileAsync()はcompile()より大幅に遅くなります。非同期のカスタムインポーターや関数が不要であれば、同期版を使ってください。
4. カスタムインポーター — @use / @import の解決をカスタマイズ
import * as sass from 'sass';
import * as path from 'path';
const result = sass.compile('src/styles/main.scss', {
importers: [
{
// 「~」プレフィックスを node_modules に解決するカスタムインポーター
findFileUrl(url: string): URL | null {
if (!url.startsWith('~')) return null;
const modulePath = url.substring(1);
return new URL(
`file://${path.resolve('node_modules', modulePath)}`
);
},
},
],
});
5. カスタム関数 — Sass から JavaScript 関数を呼び出す
Sass のスタイルシート内から JavaScript の関数を呼び出せます。
import * as sass from 'sass';
const result = sass.compileString(
`
$width: pow(2, 10);
.container {
width: #{$width}px;
}
`,
{
functions: {
// Sass側の関数シグネチャ: 引数名と型
'pow($base, $exponent)': (args: sass.Value[]): sass.Value => {
const base = args[0].assertNumber('base').value;
const exponent = args[1].assertNumber('exponent').value;
return new sass.SassNumber(Math.pow(base, exponent));
},
},
}
);
console.log(result.css);
// .container { width: 1024px; }
類似パッケージとの比較
| 特徴 | sass(Dart Sass) | node-sass(LibSass) | sass-embedded |
|---|---|---|---|
| 実装言語 | Dart → JS にコンパイル | C++(ネイティブバインディング) | Dart(ネイティブバイナリ) |
| インストール | 純JS、依存なし | ネイティブビルドが必要 | プラットフォーム別バイナリ |
| 速度 | 中程度 | 速い(ただし機能追加が停滞) | 最速 |
| Sass 最新仕様対応 | ✅ 常に最新 | ❌ 非推奨・開発停止 | ✅ 常に最新 |
@use / @forward | ✅ | ❌ | ✅ |
| API 互換性 | Modern API + Legacy API | Legacy API のみ | Modern API + Legacy API |
| メンテナンス状況 | ✅ 活発 | ❌ 非推奨 | ✅ 活発 |
結論: 新規プロジェクトでは sass または sass-embedded を選択してください。node-sass は非推奨であり、最新の Sass 仕様(@use / @forward など)に対応していません。パフォーマンスが重要な場合は sass-embedded が最適ですが、ネイティブバイナリへの依存が発生します。
注意点・Tips
1. compile() と compileAsync() の使い分け
// ✅ 推奨:同期版を使う(高速)
const result = sass.compile('main.scss');
// ⚠️ 非同期版は必要な場合のみ(カスタム非同期インポーターなど)
const result2 = await sass.compileAsync('main.scss');
公式が明言しているとおり、compileAsync() は compile() より大幅に遅いです。非同期のカスタムインポーターや関数が不要であれば、常に同期版を使いましょう。
2. Legacy API(renderSync / render)は使わない
// ❌ Legacy API — Dart Sass 2.0 で削除予定
const result = sass.renderSync({ file: 'main.scss' });
// ✅ Modern API を使う
const result2 = sass.compile('main.scss');
renderSync() / render() は Node Sass 互換のために残されている Legacy API です。新規プロジェクトでは必ず Modern API(compile / compileString)を使ってください。
3. outputStyle は2種類のみ
expanded(デフォルト)と compressed のみサポートされています。Ruby Sass にあった nested や compact は使えません。
4. ソースマップの扱い
import * as sass from 'sass';
import * as fs from 'fs';
const result = sass.compile('src/styles/main.scss', {
sourceMap: true,
sourceMapIncludeSources: true, // ソースマップにSCSSソースを埋め込む
});
fs.writeFileSync('dist/main.css', result.css);
fs.writeFileSync(
'dist/main.css.map',
JSON.stringify(result.sourceMap)
);
5. Vite / Webpack での利用
sass パッケージをインストールするだけで、多くのバンドラーが自動的に検出して利用します。
// vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
css: {
preprocessorOptions: {
scss: {
// Modern API を使用(Vite 5.4+)
api: 'modern-compiler',
additionalData: `@use "src/styles/variables" as *;`,
},
},
},
});
6. UTF-8 のみサポート
Dart Sass は現在 UTF-8 エンコーディングのみをサポートしています。Shift_JIS や EUC-JP のファイルを扱う場合は、事前に UTF-8 に変換してください。
まとめ
sass は、ネイティブ依存なしで動作する公式の Sass コンパイラであり、最新の Sass 仕様に常に追従しています。新規プロジェクトでは Modern API(compile / compileString)を使い、パフォーマンスが必要な場合は同期版を優先してください。node-sass からの移行先としても最適な選択肢です。