JavaScript

【Node.js】npmからDartSassを使う【LibSassは非推奨になった】

こんにちは、おぐらです。
過去にSassのコンパイルについてまとめた記事を投稿しましたが、最近になってSassに動きがあったので再度作成しました。

この記事はDartSassをnpmから使う方法を簡単にまとめた記事です。
npmから使うことに焦点を当てているので、DartSassの詳しい書き方などには触れていません。

npmでNodeSassパッケージを使っている人や、これからnpmを使ってSassのプロジェクトをはじめる人にオススメです。

npmからDartSassを使う

まずはなぜ使うのかを話します。
それから簡単な使い方をみていきましょう。

LibSassは非推奨になった

2020年10月にSassの公式からLibSassは非推奨と正式にリリースがありました。
LibSassによってつくられているNodeSassパッケージも含まれます。

Sass公式は主なポイントとして次の4つをあげています。

  • 新しいSassプロジェクトにLibSassを使うことを推奨しません。 代わりにDartSassを使用してください。
  • 既存のすべてのLibSassユーザーが最終的にDartSassに移行する計画を立て、すべてのSassライブラリが最終的にLibSassのサポートを終了する計画を立てることをオススメします。
  • 新しいCSS機能との互換性など、LibSassに新しい機能を追加する予定はありません。
  • LibSassとNodeSassは、主要なバグやセキュリティの問題の修正、最新のNodeバージョンとの互換性の維持など、ベストエフォートベースで無期限に維持され続けます。

明確に代わりにDartSassを使ってくれと書かれていますね。
今後もLibSassを使っていくには問題が多かったようです。

npmでDartSassをインストール

まずは簡単な例としてプロジェクトを作成します。
プロジェクトを作成したらDartSassパッケージをインストール。

紛らわしいですが、DartSassインストール時のパッケージ名はsass。
間違えないようにしましょう。

npm init
npm install sass --save-dev

プロジェクト直下にsrcディレクトリを作成、その中にapp.scssを配置しておきます。
コンパイルできることを確認するためだけなので、内容はシンプルです。

// src/app.scss
@use "sass:map";

$sizes: (
  sm: 100px,
  md: 200px,
  lg: 300px,
);

.hoge {
  width: map.get($sizes, sm);
}

yarnの場合は適宜変更してください。

コマンドからコンパイル

1番手っ取り早いのはコマンドでコンパイルする方法でしょう。
ターミナルからsassコマンドを使います。

// sass  [output.css]
npx sass src/app.scss dist/app.css

1つ以上のファイルをコンパイルするときはMany-to-many Modeを使います。

npx sass hoge.scss:hoge.css piyo.scss:piyo.css

ディレクトリ対ディレクトリも可能です。

npx sass src:public/css

オプションを渡すこともできます。
よく使うものだとウォッチモードでファイルを監視したり、コンパイルのスタイルを変更したりでしょうか。

// compressedスタイルでコンパイルする
npx sass src/app.scss dist/app.css --style=compressed
// watchモードでファイルの更新を監視する
npx sass src/app.scss dist/app.css --watch

オプションはヘルプオプションを渡せば確認できます。
ヘルプを見る限りstyleは2種類しかなさそうですね。

npx sass --help // -hと省略可能です

例ではnpxを使ってますが、npm-scriptsに指定してもらっても大丈夫です。

NodeSassパッケージと互換性あり

JavaScriptpから使おうとした場合、一部を除いてnode-sassパッケージと同じように使えます。
次はrenderとrenderSyncを使った例です。

const sass = require('sass');

sass.render({
  file: './src/app.scss'
}, (err, result) => {
  // Do something
});

const data = sass.renderSync({file: './src/app.scss'});

renderはコールバックの引数resultに、renderSyncは戻り値としてコンパイルしたデータを受け取ります。
File systemモジュールを使ってよしなにファイルにしてあげるなどしてください。

render関数はコールバックオーバーヘッドの関係で、renderSync関数と比較してパフォーマンスが落ちます。
対策としてfibersを使うことでパフォーマンス改善できると記されています。

const sass = require('sass');
const Fiber = require("fibers");

sass.render({
  file: './src/app.scss',
  fiber: Fiber,
}, (err, result) => {
  // Do something
});

コンパイル時間を比較すると確かにrenderSyncはかなり速いですね。
renderもfibersを使うことで半分以下になったので使ったほうがいいですね。

応用編

応用編としてwebpackでも使う方法を簡単にまとめておきます。
といってもsass-loaderを使うことに変わりは無くて、コンパイル用に用意するパッケージをDartSassにするだけです。

webpackでバンドルする

webpackを使うためのパッケージをインストールします。
はじめつくったプロジェクトに追加するので、DartSassとfibersはすでにインストール済みとします。

npm install webpack webpack-cli sass-loader css-loader style-loader --save-dev

エントリーファイルのindex.jsをsrcディレクトリに作成して、app.scssをインポートしておきます。

// ./src/index.js
import './app.scss';

続いてwebpackの設定ファイルを作成。
プロジェクトルートにwebpack.config.jsを追加します。

const path = require('path');

module.exports = {
  entry: path.join(__dirname, 'src'),
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          'style-loader',
          'css-loader',
          'sass-loader',
        ],
      },
    ],
  },
};

そして確認用としてdistにindex.htmlを追加。
バンドルしたJavaScriptファイルを読み込みます。

最後にビルドしましょう。

npx webpack

style要素として出力されてます。

上記はとても簡単な例です。
ほかのローダーも組み合わせることでさらに柔軟にバンドルできます。

CSSファイルを個別ファイルにする

CSSはファイルを別にしたい場合もあるでしょう。
webpackのMiniCssExtractPluginを使うことで解決できます。

webpack.config.jsにプラグインを追加する記述を追加。
最終的にstyle-loaderではなく、MiniCssExtractPluginを使うことでCSSファイルとして出力できます。

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  entry: path.join(__dirname, 'src'),
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'sass-loader',
        ],
      },
    ],
  },
  resolve: {
    extensions: ['.js'],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "app.css",
    }),
  ],
};

NodeSassがプロジェクト内にある場合

NodeSassがプロジェクトに含まれている場合、DartSassを使うことを明示的にwebpackに伝えます。
webpack.config.jsに追加するだけで簡単にできますよ。

module: {
  rules: [
    {
      test: /\.s[ac]ss$/i,
      use: [
        'style-loader',
        'css-loader',
        {
          loader: 'sass-loader',
          options: {
            implementation: require('sass'),
          },
        },
      ],
    },
  ],
},

上記はmoduleのところだけを抜粋しています。
今までNodeSassを使ってきてDartSassに移行する時必要かもしれませんね。

プロジェクトにfibersをインストールしていれば自動で注入してくれます。
逆に自動注入をしたくない場合は明示的に設定が必要です。

{
  loader: 'sass-loader',
  options: {
    implementation: require('sass'),
    sassOptions: {
      fiber: false,
    },
  },
},

これからはじめる人はDartSassを使おう

これからSassを学ぶ、プロジェクトをはじめるならDartSassを使いましょう。
LibSassは非推奨になり、メンテナンスは続けられますが、今後追加される新しい機能などとの互換
性はありません。

npmのNodeSassパッケージもLibSassでできているので、これからは使わないようにしましょう。
面倒ですがわたしもNodeSass使ってるプロジェクトをDartSassに移行します。

 

参考リンク

LibSass is Deprecated
sass – npm
Dart Sass Command-Line Interface
JavaScript API
fibers – npm
sass-loader | webpack
MiniCssExtractPlugin | webpack